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

Ste*_*zan 18 java encoding utf-8 java-8

使用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);
    }
}
Run Code Online (Sandbox Code Playgroud)

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

 65533
Run Code Online (Sandbox Code Playgroud)

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

 57052
Run Code Online (Sandbox Code Playgroud)

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

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

Hol*_*ger 12

它是" 修改的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();
Run Code Online (Sandbox Code Playgroud)


McD*_*ell 6

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中修复的错误.