在Java中,如何正确地将byte[]转换为String再转回byte[]?

3

我希望将TEA加密的结果(一个byte[]数组)转换为字符串,然后再将其转换回byte[]数组,并获取相同的byte[]数组。

//Encryption in the sending side
String stringToEncrypt = "blablabla"
byte[] encryptedDataSent = tea.encrypt(stringToEncrypt.getBytes());
String dataToSend = new BigInteger(encryptedDataSent).toString());

//Decryption side in the reception side
byte[] encryptedDataReceived = new BigInteger(dataToSend).toByteArray();

然而,当我尝试这样做时:
System.out.println(new String(encryptedDataSent));

System.out.println(new String(encryptedDataReceived));

boolean equality = Arrays.equals(encryptedDataReceived,encryptedDataSent);
System.out.println("Are two byte arrays equal ? : " + equality);

输出结果为:

&h�7�"�PAtj݄�I��Z`H-jK�����f

&h�7�"�PAtj݄�I��Z`H-jK�����f

两个byte数组相等吗?:false

所以,当我们打印它们时,这两个byte[]看起来是相同的,但实际上它们并不完全相同,因为我们看到了“false”,这对于我之后的解密工作是一个问题。
我还尝试发送一个String with new String(byte[]),但在将其转换回byte[]时,它具有相同的问题。
我希望一开始和转换后的byte[]完全相同。
您是否有解决方案或了解我在转换中做错了什么?

请查看以下两个链接,它们可能会有所帮助:字符串转换为字节数组和反之另一个链接 - user45
4个回答

3
不要试图将 byte [] 转换为 String ,就像它是常规编码文本数据一样-它不是。它是一个任意的字节数组。 最简单的方法是将其转换为base64或十六进制-这将导致ASCII文本,可以反向解码回相同的二进制数据。例如,使用公共领域base64编码器
String dataToSend = Base64.encodeBytes(encryptedDataSent);
...
byte[] encryptedDataReceived = Base64.decode(receivedText);

谢谢您的回答。但是,如果我的需求是将byte[]数据写入文本文件,然后能够复制该文本,粘贴到字段中并检索数据,则应以什么格式存储byte[]数据在文本文件中? - red.and.black
@RédaBk:我会使用base64来实现,就像我展示的那样。 - Jon Skeet
谢谢@JonSkeet,它起作用了!Base64编码给了我一个像这样的字符串(AAAAKSvMGMmVa75daqF+XuFyDdnbDrhljLsv8o+fl7ZOfE5rdEOVv5EIxrQBGy2FgQVVwQ==),然后我能够再次将其转换为原始的byte[]!为什么这个字符串编码适用于正确的字节转换而其他编码不适用呢?想知道... - red.and.black

1
尝试在解密中使用 byte[] encode = Base64.encode(bytesToStore, Base64.DEFAULT)

0

你无法这样做。String不是二进制数据的容器,而是UTF-16字符的容器。字符和字节之间的往返转换并不保证。


你不能那样做,但是认为你不能将任意二进制数据表示为文本,然后将其转换回相同的二进制数据显然是有缺陷的...十六进制、base64、base32...存在许多方法。 - Jon Skeet

-2

尝试显式指定字符集。对于大多数情况,UTF-8都可以使用:

public static void main(String[] args) {
    String in = "幸福";
    try {
        byte[] bytes = in.getBytes("utf-8");
        String out = new String(bytes, "utf-8");
        System.out.println(in + " -> " + out);
        System.out.println("equals: " + out.equals(in));
    } catch (UnsupportedEncodingException unsupportedEncodingException) {
        // do something
    }
}

请注意,只要字节数组保持不变,您将获得完全相同的结果。

不,当数据是任意二进制数据而不是UTF-8编码的文本时,UTF-8是不可行的。OP想要将加密结果转换为文本。那不是UTF-8编码的文本。 - Jon Skeet

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接