簡體   English   中英

Java UTF-8的區別

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM