但这甚至意味着什么?在这种情况下,什么是嵌入式null?我试图将Java保存的UTF-8字符串转换为“真正的”UTF-8。
答案 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()
编写的,则序列化规范是明确的。