2012-02-04 199 views
1

如果我有一些二进制数据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 
    } 
} 

为什么会发生这种情况?

+0

你试图强制任意的二进制数据到一个字符串?为什么? – Jesper 2012-02-04 20:22:00

+0

(如果*由于某种原因必须隐藏字符串中的二进制数,则需要使用提供字节和字符之间的一对一映射的编码; ISO-8859-1将是明显的选择UTF-8的字节序列不代表有效字符。) – bobince 2012-02-05 09:29:21

回答

2

将字节数组转换为字符串并再次返回不是一对一的映射操作。读取docs时,字符串implmentation使用CharsetDecoder将传入的字节数组转换为unicode。输入字节数组中的第一个字节和最后一个字节不得映射为有效的Unicode字符,因此它将替换为一些replacement string

+0

好点。但这似乎很奇怪。为什么它应该使用一些魔术替代字符串而不是抛出异常? – 2012-02-04 20:11:54

+0

我猜CharsetDecoder遇到一个不可映射的字符时抛出一个异常是可能的,但是默认的String实现使用一个默认错误字符的较不易变的选项。我敢打赌你可以自己使用CharsetDecoder来控制Byte [] <->字符串转换。 – 2012-02-04 20:27:27

1

这很可能是您转换为字符串的字节实际上并不构成有效的字符串。如果java无法弄清楚每个字节的意思,它会尝试修复它们。这意味着当你转换回字节数组时,它不会和你启动时一样。如果你尝试使用一组有效的字节,那么你应该会更成功。

+0

是的。但我至少除了在这种情况下得到例外。 – 2012-02-04 20:03:42

+0

行为是可配置的 - 您可以忽略,替换或错误。请参阅http://docs.oracle.com/javase/1.5.0/docs/api/java/nio/charset/CharsetDecoder.html,特别是有关CodingErrorAction类 – DNA 2012-02-04 20:33:23

+0

@DNA的位,谢谢您的好意。 – 2012-02-04 20:44:21

0

使用UTF-8编码无法将您的数据解码为有效的Unicode字符。看看解码后的字符串。它由3个字符组成:0xFFFD0x00680xFFFD。首先和最后是“ ” - Unicode replacement characters。我认为你需要选择其他编码。即“CP866”生成有效的字符串并将其转换回相同的数组。

相关问题