Java中的字节数组转换为字符串及其反向操作:恢复的字节数组与原始字节数组不匹配。

4

我在Java中将字节数组转换为字符串,代码如下:

String str_bytearray = new String(bytearray_original);

然后,我使用字符串将原始字节数组恢复,如下所示:
byte[] bytearray_recovered = str_bytearray.getBytes();

然而当我比较原始字节数组 bytearray_original 和恢复后的字节数组 bytearray_recovered 时,我有些担心。结果如下:

[48, 89, 48, 19, 6, 7, 42, -122, 72, -50, 61, 2, 1, 6, 8, 42, -122, 72, -50, 61, 3, 1, 7, 3, 66, 0, 4, 100, -27, 48, -31, 13, -33, 107, -90, 91, -9, 119, 121, -73, 83, -105, 51, -87, -109, -84, 99, 115, -123, 119, -117, -1, -62, 71, -32, 99, 4, -103, -115, -47, 113, -83, 8, -91, 14, -74, 113, -40, -26, 50, 111, 95, 71, -9, 112, 120, 16, 0, 113, -80, 124, -71, 53, -97, 69, -85, 38, -112, -30, -110, 115]

[48, 89, 48, 19, 6, 7, 42, -122, 72, -50, 61, 2, 1, 6, 8, 42, -122, 72, -50, 61, 3, 1, 7, 3, 66, 0, 4, 100, -27, 48, -31, 13, -33, 107, -90, 91, -9, 119, 121, -73, 83, -105, 51, -87, -109, -84, 99, 115, -123, 119, -117, -1, -62, 71, -32, 99, 4, -103, 63, -47, 113, -83, 8, -91, 14, -74, 113, -40, -26, 50, 111, 95, 71, -9, 112, 120, 16, 0, 113, -80, 124, -71, 53, -97, 69, -85, 38, 63, -30, -110, 115]

正如您所看到的,与原始字节数组不同的是两个字节,即-115到63-112到63。是否有可能解决这个问题?
注意:实际上,原始和恢复的字节数组都是公钥。首先,将公钥转换为字符串以存储在文件中,然后在读取公钥的字符串值后,应恢复公钥以验证签名。
bytearray_original生成如下:
PublicKey signPublicKey = keypair.getPublic(); 
byte [] bytearray_original = signPublicKey.getEncoded();

我很感激您的帮助。
敬礼

这个转换的目的是什么?你想在某个地方将字节数组存储为字符串,还是只是出于好奇? - sainaen
@sainaen,实际上原始的和恢复后的字节数组都是公钥。首先将公钥转换为字符串以存储在文件中,然后在读取公钥的字符串值后,应该进行恢复以验证签名。 - Questioner
哦,好的,那么你可能正在使用类似于bouncycastle这样的工具来进行加密。你可以尝试一下org.bouncycastle.util.encoders.Hex.toHexString()Hex.decode()这样的方法——它们适用于任意二进制数据。 - sainaen
@sainaen,没错。但是我不知道如何在我的代码中使用你的代码。如果你能帮我把它加入到我的代码中,我会非常感激。谢谢。 - Questioner
啊,这个不会被编码成UTF-8字符串,因为它是一堆随机数据。相反,你应该使用Base64编码你的数据,就像Louis Wasserman的回答中所示,或者使用十六进制编码。 - Trent Small
3个回答

13
你不能将任意字节序列转换为 String,并期望逆转换工作。你需要使用像 Base64 这样的编码来保留任意字节序列。(这在几个地方都可以使用--Java 8 内置,也可以从 Guava 和 Apache Commons 获取。)
例如,在 Java 8 中,
String encoded = Base64.getEncoder().encodeToString(myByteArray);

可逆的,需要使用

byte[] decoded = Base64.getDecoder().decode(encoded);

请给我一个例子好吗?谢谢。 - Questioner

1
作为Louis Wasserman的答案的替代方案,只要您的项目中有BouncyCastle,您可以使用org.bouncycastle.util.encoders.Hex实用程序类:
import org.bouncycastle.util.encoders.Hex;
import java.util.Arrays;

class EncodingTest {
    public static void main(String[] args) {
        byte[] bytearray_original = new byte[]{48, 89, 48, 19, 6, 7, 42, -122, 72, -50, 61, 2, 1, 6, 8, 42, -122, 72, -50, 61, 3, 1, 7, 3, 66, 0, 4, 100, -27, 48, -31, 13, -33, 107, -90, 91, -9, 119, 121, -73, 83, -105, 51, -87, -109, -84, 99, 115, -123, 119, -117, -1, -62, 71, -32, 99, 4, -103, -115, -47, 113, -83, 8, -91, 14, -74, 113, -40, -26, 50, 111, 95, 71, -9, 112, 120, 16, 0, 113, -80, 124, -71, 53, -97, 69, -85, 38, -112, -30, -110, 115};
        String str_bytearray = Hex.toHexString(bytearray_original);
        byte[] bytearray_recovered = Hex.decode(str_bytearray);
        System.out.println("Results are equal: " + Arrays.equals(bytearray_original, bytearray_recovered));
    }
}

这个选项需要使用外部库,但不需要 Java 8。


0

指定编码方式可能会有所帮助,比如使用UTF-8。

String构造函数和getBytes方法都可以让您实现这一点,例如:

String str_bytearray = new String(bytearray_original, "UTF-8");
byte[] bytearray_recovered = str_bytearray.getBytes("UTF-8");

这应该会导致相同的字节数组。

编辑:正如RealSkeptic所指出的那样,您需要确定原始字节数组使用的编码方式,并在上述代码中使用该编码方式替换“UTF-8”。


1
只有当原始字节实际上是UTF-8编码时才能这样做。 - RealSkeptic
@Trent Small,情况更糟,甚至长度都不一样。结果如下:原始数据: [48, 89, 48, 19, 6, 7, 42, -122, 72, -50, 61, 2, 1, 6, 8, 42, -122, 72, -50, 61, 3, 1, 7, 3, 66, 0, 4, 107, 38, -108, 75, 125, 75, -103, -70, 68, 103, -120, 78, 113, -98, -111, 106, 38, -125, -93, -102, -22, -37, 30, 25, 61, -15, -90, -47, 76, -25, 16, -9, 14, 3, 19, -115, 27, 39, -77, -55, -12, -54, 85, 69, -76, 53, -3, 94, -107, 124, 61, 100, 49, -21, -61, -21, -54, 112, -47, -16, -50, -47, -106, -13]。 - Questioner
恢复的数据: [48, 89, 48, 19, 6, 7, 42, -17, -65, -67, 72, -17, -65, -67, 61, 2, 1, 6, 8, 42, -17, -65, -67, 72, -17, -65, -67, 61, 3, 1, 7, 3, 66, 0, 4, 107, 38, -17, -65, -67, 75, 125, 75, -17, -65, -67, -17, -65, -67, 68, 103, -17, -65, -67, 78, 113, -17, -65, -67, -17, -65, -67, 106, 38, -17, -65, -67, -17, -65, -67, -17, -65, -67, -17, -65, -67, -17, -65, -67, 30, 25, 61, -17, -65, -67, -17, -65, -67, 76, -17, -65, -67, 16, -17, -65, -67, 14, 3, 19, -17, -65, -67, 27, 39, -17, -65, -67, - Questioner
@sas请不要滥用评论区。如果您有长篇信息要添加,请将其作为问题的编辑添加:“我这样做,得到的结果是如此如此”,然后您可以在答案下评论并说“看一下我问题的编辑”。 - RealSkeptic
@TrentSmall,我编辑了我的问题并添加了一些有关如何生成原始字节数组的附加信息。 - Questioner
显示剩余5条评论

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