[英]Java UTF-8 differences
JavaDoc說“空字節'\\ u0000'以2字節格式而不是1字節編碼,因此編碼的字符串永遠不會嵌入空值。”
但這甚至意味着什么呢? 在這種情況下,什么是嵌入式null? 我試圖從Java保存的UTF-8字符串轉換為“真正的”UTF-8。
在C中,字符串由字節值00終止。
這里的事情是你可以在Java字符串中使用0-chars但是為了避免在將字符串傳遞給C(所有本地方法都寫入)時出現混淆,字符以另一種方式編碼,即作為兩個字節
11000000 10000000
(根據javadoc)這兩者實際上都不是00。
這是一個解決你無法輕易改變的事情的黑客。
另請注意,這是有效的UTF-8並正確解碼為00。
沒有“嵌入空值”表示原始數據不包含單個0x00
(NULL)字節。
\
被編碼為(二進制) 11000000 10000000
,(十六進制) 0xC080
。
這不是Java范圍的差異,僅在DataInput/OutputStream
。 如果字符串數據是使用DataOutputStream
編寫的,那么只需使用DataInputStream
讀取它。
如果您需要將字符串數據寫入文件,請不要使用DataOutputStream
,請使用Writer
,它適用於字符流。
這僅適用於DataOutputStream的writeUTF
方法,不適用於正常轉換的流(OutputStreamWriter等)。
這意味着如果你有一個字符串"\ "
,它將編碼為0xC0 0x80
而不是簡單的0x00
。
而在另一方面,這個序列0xB0 0x80
,它永遠不會出現在普通的UTF-8字符串中,代表一個空字符。
此外,您鏈接的文檔似乎來自Unicode仍然是16位字符集的時間 - 現在它還允許超過0xFFFF的char
每個char
將由兩個Java char
值表示(以UTF-16格式,代理如果我計算得正確的話,將需要UTF-8中的4個字節。 我注意到這里的實現確實 - 看起來這些只是用CESU-8格式編寫的(例如兩個3字節序列,每個序列對應一個UTF-16代理,它們一起給出一個Unicode字符)。 你也必須要照顧好這一點。
如果您使用的是Java,最簡單的方法是使用DataInputStream將其讀入字符串,然后將其轉換(使用getBytes("UTF-8")
或OutputStreamWriter轉換為真正的UTF-8數據)。
如果您在閱讀“已保存”的Java字符串時遇到困難,則需要查看以該格式讀/寫的方法的規范:
如果字符串是使用DataOutput.writeUTF8編寫的,則DataInput.readUTF8()
javadoc是一個明確的規范。 除了NUL
的非標准處理之外,它還指定字符串以無符號的16位字節計數開頭。
如果字符串是使用ObjectOutputStream.writeObject()
編寫的,則序列化規范是確定的。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.