1. 程式人生 > >[Java]字串轉Unicode編碼額外2個位元組的來源

[Java]字串轉Unicode編碼額外2個位元組的來源

轉載:

https://blog.csdn.net/iteye_3946/article/details/81640056

https://www.zhihu.com/question/23374078/answer/69732605

 

為了在讀取位元組時能知道所採用的位元組序,在傳輸時採用了一個名為 “ZERO WIDTH NON-BREAKING SPACE”(U+FEFF)的字元用於限定位元組序, 開頭兩個位元組為 FE FF 時為 Big-Endian,為 FF FE 時為 Little-Endian。  詳見 RFC2781 3.2 節。  

在 Java 中直接使用 Unicode 轉碼時會按照 UTF-16LE 的方式拆分,並加上 BOM。   如果採用 UTF-16 拆分,在 Java 中預設採用帶有 BOM 的 UTF-16BE 拆分。

Little-Endian:就是低位位元組排放在記憶體的低地址端,高位位元組排放在記憶體的高地址端。

Big-Endian:就是高位位元組排放在記憶體的低地址端,低位位元組排放在記憶體的高地址端。

為什麼UTF-8中看不到BOM頭?

Unicode符號範圍        |   UTF-8編碼方式

(十六進位制)             | (二進位制)       #Unicode部分為16進位制編碼, UTF-8編碼為2進位制

—————————————————————–————————————–
0000-0000 007F   | 0xxxxxxx      #UTF-8規定,若1字元=1位元組,首位須為‘0’
0080-0000 07FF   | 110xxxxx 10xxxxxx  #UTF-8規定,若1字元=2位元組,高位位元組前3位為‘110’,低位前2位為‘10’
0800-0000 FFFF   | 1110xxxx 10xxxxxx 10xxxxxx  #UTF-8規定,若1字元=3位元組,高位位元組前3位為‘110’,後面低位前2位一律為‘10’。(佔4,5位元組字元規則以此類推)

UTF-8 是採用 1~4 個位元組來表示 Unicode 字元的,每個 Unicode 的 UTF-8 編碼的 第一個位元組是有一定範圍的,如果讀取到某個位元組的最高位為 0 那麼採用一個位元組表 示,如果最高位是兩個“1”就採用兩個位元組表示,最高位是三個“1”採用三個位元組表 示,以此類推。多位元組表示時,第二個和後面的位元組的最高位只能是“10”,也就是說 UTF-8 編碼時字元的第一個位元組的最高位不可能是“10”。  因此,UTF-8 只能採用 Big-Endian 的 BOM 方式。BOM 頭 U+FEFF,UTF-8 編碼為 EF BB BF 就穩含掉了。

測試:

System.out.println("Unicode");
System.out.println("中"+Arrays.toString("中".getBytes("Unicode")));
System.out.println("文"+Arrays.toString("文".getBytes("Unicode")));
System.out.println("中文"+Arrays.toString("中文".getBytes("Unicode")));

System.out.println("UTF-8");
System.out.println("中"+Arrays.toString("中".getBytes("UTF-8")));

System.out.println("GBK");
System.out.println("中"+Arrays.toString("中".getBytes("GBK")));

輸出:

在輸出結果中可以看到,將字串轉換成Unicode編碼的位元組陣列時,陣列存在額外位元組-2,-1。位元組-2的補碼為0xFE,位元組-1的補碼為0xFF,連起來FEFF表示Big-Endian。