2011-06-25 23 views
3

我想将一个java字符串序列化成一个字节数组,然后将数组反序列化为一个字符串。它似乎工作正常,直到我测试了一个Unicode字符\ude4e。出于某种原因,原始字符串"\ud34e"不等于反序列化的字符串。Java String-> unicode->字符串转换不一致

这是序列化代码(其中encoding = Charset.forName("UTF-16BE")str = "\ud34e"

ByteArrayOutputStream out = new ByteArrayOutputStream(); 

Writer temp = new OutputStreamWriter(out, encoding); 

temp.write(str); 

temp.close(); 

byte[] bytes = out.toByteArray(); 

String deserialized = new String(bytes, encoding); 

那我做错了吗? 谢谢!

+1

'res.toByteArray()' - >'bytes'? – aioobe

+0

哎呀,你是对的。错字。修复。 –

回答

6

DE4E是代理对的1/2。它本身就是无效的。它会被转换为?或由OutputStreamWriter丢弃。如果你使用java.nio类,你可以看到错误。

1
public static void main(String[] args) throws IOException { 
    Charset encoding = Charset.forName("UTF-16BE"); 

    ByteArrayOutputStream out = new ByteArrayOutputStream(); 

    Writer temp = new OutputStreamWriter(out, encoding); 

    String str = "\ud34e"; 

    temp.write(str); 

    temp.close(); 

    byte[] bytes = out.toByteArray(); 

    String deserialized = new String(bytes, encoding); 

    System.out.println("'" + str + "'/'" + deserialized + "'/" + (str.equals(deserialized))); 
} 

对我来说,输出是:

'?'/'?'/true 

即他们是平等的......

我使用: Java版本 “1.6.0_24” 的Java(TM) SE运行时环境(版本1.6.0_24-b07) Java HotSpot™64位服务器VM(版本19.1-b02,混合模式)

3

当我在在线Unicode charts上查找代码de4e时,它表示此代码位于低代理图表中。它本身不是一个字符,而是UTF-16中使用的特殊代码(根据文档)。

Unicode并不像单个字符映射到单个代码点那么简单 - 有许多怪癖和事物,并且不同的代码点和字节序列可能指向相同的字符。

当序列化和反序列化时,某些代码点可能会导致不同但等效的代码点。

0

虽然它不是一个有效的字符,@Ant显示编码解码返回原始。这可能是因为UTF-16是一个非常简单的&直接编码,与Java的16位char表示法一致。

如果我们尝试使用UTF-8,编码应该会引发一个致命错误。 UTF-8无法编码代理对的一半。