编码和解码后字符串不同

时间:2018-05-13 19:39:11

标签: java string unicode character-encoding unicode-literals

我偶然发现了编码/解码字符串的奇怪行为。看一个例子:

@Test
public void testEncoding() {
    String str = "\uDD71"; // {56689}
    byte[] utf16 = str.getBytes(StandardCharsets.UTF_16); // {-2, -1, -1, -3}
    String utf16String = new String(utf16, StandardCharsets.UTF_16); // {65533}
    assertEquals(str, utf16String);
}

我认为这个测试会通过,但事实并非如此。有人可以解释为什么编码和解码的字符串不等于原始字符串吗?

1 个答案:

答案 0 :(得分:4)

U+DD71不是有效的代码点,因为U + D800..U + DFFF由Unicode保留,以免引起与UTF-16的混淆。因此,这些代码点永远不应显示为有效的字符数据。从Unicode标准:

  

孤立的代理代码点没有解释;因此,没有提供字符代码图表或名称列表   这个范围。

但这有效:

@Test
public void testEncoding() {
    String str = "\u0040";
    byte[] utf16 = str.getBytes(StandardCharsets.UTF_16);
    String utf16String = new String(utf16, StandardCharsets.UTF_16);
    assertEquals(str, utf16String);
}

因此,您的代码不是错误的,但是您尝试使用的代码点无效。