Java UTF-8的区别

时间:2011-06-22 12:24:52

标签: java utf-8

JavaDoc说"The null byte '\u0000' is encoded in 2-byte format rather than 1-byte, so that the encoded strings never have embedded nulls."

但这甚至意味着什么?在这种情况下,什么是嵌入式null?我试图将Java保存的UTF-8字符串转换为“真正的”UTF-8。

5 个答案:

答案 0 :(得分:16)

在C中,字符串由字节值00终止。

这里的事情是你可以在Java字符串中有0个字符但是为了避免在将字符串传递给C(所有本地方法都被写入)时出现混淆,该字符在另一个字符串中编码方式,即两个字节

11000000 10000000

(根据javadoc)这两者实际上都不是00.

这是一个解决你无法轻易改变的事情的黑客。

另请注意,这是有效的UTF-8并正确解码为00。

答案 1 :(得分:4)

否“嵌入空值”表示原始数据不包含单个0x00(NULL)字节。

\u0000被编码为(二进制)11000000 10000000,(十六进制)0xC080

答案 2 :(得分:1)

仅在DataInput/OutputStream中,这不是Java范围的差异。如果字符串数据是使用DataOutputStream编写的,那么只需使用DataInputStream读取它。

如果您需要将字符串数据写入文件,请不要使用DataOutputStream,请使用Writer,这是用于字符流的。

答案 3 :(得分:1)

这仅适用于DataOutputStream的方法writeUTF,不适用于正常转换的流(OutputStreamWriter等)。

这意味着如果您有一个字符串"\u0000",它将被编码为0xC0 0x80,而不仅仅是0x00

反过来说,这个序列0xB0 0x80在普通的UTF-8字符串中永远不会出现,代表一个空字符。

此外,您链接的文档似乎是从Unicode仍然是16位字符集开始的时候 - 现在它还允许超过0xFFFF的字符,每个字符将由两个Java char值表示(在UTF-16格式,代理对),如果计算正确,将需要UTF-8中的4个字节。我注意到这里的实现确实 - 看起来这些只是用CESU-8格式编写的(例如两个3字节序列,每个序列对应一个UTF-16代理,它们共同给出一个Unicode字符) 。你也必须要照顾好这一点。

如果您使用的是Java,最简单的方法是使用DataInputStream将其读入字符串,然后将其(使用getBytes("UTF-8")或OutputStreamWriter转换为真正的UTF-8数据。

答案 4 :(得分:0)

如果您在阅读“已保存”的Java字符串时遇到困难,则需要查看以该格式读/写的方法的规范:

  • 如果字符串是使用DataOutput.writeUTF8编写的,则DataInput.readUTF8() javadoc是一个明确的规范。除了NUL的非标准处理之外,它还指定字符串以无符号的16位字节数开头。

  • 如果字符串是使用ObjectOutputStream.writeObject()编写的,则序列化规范是明确的。