使用UTF-8编码创建字符串时存在不一致。
运行此代码:
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更为紧迫。
答案 0 :(得分:12)
“Modified UTF-8”编码的属性用于存储代理对(甚至是该范围的未配对字符),如单个字符。如果声称使用标准UTF-8
的解码器使用“修改的UTF-8 ”,则会出错。这似乎已经用Java 8修复了。
您可以使用指定的方法可靠地读取此类数据,以使用“修改的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();
答案 1 :(得分:5)
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中修复的错误。
答案 2 :(得分:3)
这是代理人,对吧?我不是Unicode专家,但我不认为它本身就有意义。 Java 8已更改为支持Unicode 6.2。也许它对此更严格。 65533是标准的0xFFFD替换字符,这意味着"不可表示"。是否存在需要将其解释为字符串的真实情况?因为看起来Unicode似乎已经说不再是一个角色了。