Java 8 UTF-8编码问题(java bug?)

使用UTF-8编码创建String时存在不一致。

运行此代码:

public static void encodingIssue() throws IOException { byte[] array = new byte[3]; array[0] = (byte) -19; array[1] = (byte) -69; array[2] = (byte) -100; String str = new String(array, "UTF-8"); for (char c : str.toCharArray()) { System.out.println((int) c); } } 

在Java 1.8.0_20(及更早版本)上,我们得到了结果

 65533 

在Java 1.7和1.6上,我们得到了正确的结果:

 57052 

你遇到过这个错误吗? 这有解决方法吗?

这种不一致也体现在Shift_JIS,JIS_X0212-1990,x-IBM300,x-IBM834,x-IBM942,x-IBM942C,x-JIS0208上,但显然UTF-8更为紧迫。

它是“ 修改的UTF-8 ”编码的属性,用于存储代理对(或甚至是该范围的非配对字符),如单个字符。 如果声称使用标准UTF-8的解码器使用“ Modified UTF-8 ”,则会出错。 这似乎已经用Java 8修复了。

您可以使用指定使用“ Modified UTF-8 ”的方法可靠地读取此类数据:

 ByteBuffer bb=ByteBuffer.allocate(array.length+2); bb.putShort((short)array.length).put(array); ByteArrayInputStream bis=new ByteArrayInputStream(bb.array()); DataInputStream dis=new DataInputStream(bis); String str=dis.readUTF(); 

Java 1.6 / 1.7中收到的值是U + DEDC(低代理)。

来自RFC 3629 :

UTF-8的定义禁止在U + D800和U + DFFF之间编码字符编号,这些字符编号保留用于UTF-16编码格式(作为代理对)并且不直接表示字符。

……文字被删除了……

上述解码算法的实现必须防止解码无效序列。 例如,天真的实现可以将超长UTF-8序列C0 80解码为字符U + 0000,或将替代对ED A1 8C ED BE B4解码为U + 233B4。 解码无效序列可能会产生安全后果或导致其他问题。

Java 8将其解码为U + FFFD( REPLACEMENT CHARACTER )。 这看起来像是在Java 8中修复的错误。

那是代理人,对吧? 我不是Unicode专家,但我不认为它本身就有意义。 Java 8已更改为支持Unicode 6.2。 也许它对此更为严格。 65533是标准的0xFFFD替换字符,表示“不可表示”。 是否有一个真实的情况需要将其解释为字符串? 因为看起来Unicode似乎不再是一个角色了。