Java 将二进制数据转换为字符串

Java 将二进制数据转换为字符串,java,unicode,utf-8,Java,Unicode,Utf 8,如果我有一些二进制数据D,我把它转换成字符串S。我希望在把它转换回二进制时,我会得到D。但这是错误的 public class A { public static void main(String[] args) throws IOException { final byte[] bytes = new byte[]{-114, 104, -35};// In hex: 8E 68 DD System.out.println(bytes.length);

如果我有一些二进制数据D,我把它转换成字符串S。我希望在把它转换回二进制时,我会得到D。但这是错误的

public class A {
    public static void main(String[] args) throws IOException {
        final byte[] bytes = new byte[]{-114, 104, -35};// In hex: 8E 68 DD
        System.out.println(bytes.length);               //prints 3
        System.out.println(new String(bytes, "UTF-8").getBytes("UTF-8").length); //prints 7
    }
}

为什么会发生这种情况?

很可能您正在转换为字符串的字节实际上并不构成有效字符串。如果java无法理解每个字节的含义,它将尝试修复它们。这意味着,当您转换回字节数组时,它将与启动时不同。如果您尝试使用一组有效的字节,那么您应该会更成功。

在字节数组到字符串之间来回转换不是一对一的映射操作。读取,字符串实现使用将传入的字节数组转换为unicode。输入字节数组中的第一个字节和最后一个字节不能映射到有效的unicode字符,因此它会将其替换为一些字符。

无法使用UTF-8编码将数据解码为有效的unicode字符。看看解码的字符串。它由3个字符组成:
0xFFFD
0x0068
0xFFFD
。第一个和最后一个是“�" - . 我认为您需要选择其他编码,即“CP866”“生成有效字符串并转换回同一数组。

是的。但我至少希望在这个案例中得到例外。行为是可配置的——你可以忽略、替换或出错。请参阅,特别是关于CodingErrorAction类的部分,这是一个很好的观点。但这似乎很奇怪。为什么它应该使用一些神奇的替换字符串而不是抛出异常?我想当遇到不可映射的字符时,可以从CharsetDecoder抛出异常,但是默认字符串实现使用默认错误字符的不太易失性选项。我打赌你可以自己使用CharsetDecoder来更好地控制字节[]字符串转换。你是否试图将任意二进制数据强制转换为字符串?为什么?(如果出于某种原因必须在字符串中隐藏二进制,则需要使用在字节和字符之间提供一对一映射的编码;ISO-8859-1将是明显的选择。UTF-8具有不表示有效字符的字节序列。)