Unicode碼的二進制轉換(Java)

內容爲我的學習心得,不能對準確性作過多保證,錯誤之處還望指點。

  有時候咱們會遇到一些\u開頭的字符串,例如\u4f60\u597d,咱們知道這些是Unicode碼,一段\uxxxx字符串對應了一個Unicode字符。那這些編碼字符的實際二進制存儲格式是怎樣呢?
  咱們知道Unicode編碼能夠呈現世界上大部分的文字內容,而在其最通用的一種編碼方式UTF-8
)下,單字符的存儲長度爲1-4字節(可變),這種設計的由來和優勢就很少講了,這裏主要說說看到的u編碼串和二進制的換算方式。
  在UTF-8編碼格式的java代碼下,對「測試」兩個字打印其字節和字符結果以下:java

System.out.println(Charset.defaultCharset());
        String s = "測試";
        System.out.println(s.chars().mapToObj(Integer::toHexString).collect(Collectors.joining("\t")));
        byte[] bs = s.getBytes();
        System.out.println(Arrays.toString(bs));
        /*Result: 
        UTF-8
        6d4b    8bd5
        [-26, -75, -117, -24, -81, -107] */

  觀察結果可知,「測試」兩個字在UTF-8編碼下佔六個字節,將 【-26, -75, -117, -24, -81, -107】 6個數字轉爲二進制補碼格式,即獲得「測試」兩字的二進制存儲內容,爲:
11100110 10110101 10001011 11101000 10101111 10010101
  而經過char.ToHexString獲得的 6d4b 8bd5 是這兩個字的Unicode編碼
  這二者是怎麼關聯上的呢?
經過UTF-8的百科頁面有以下介紹:學習

UTF-8編碼字節含義
  • 對於UTF-8編碼中的任意字節B,若是B的第一位爲0,則B獨立的表示一個字符(ASCII碼);
  • 若是B的第一位爲1,第二位爲0,則B爲一個多字節字符中的一個字節(非ASCII字符);
  • 若是B的前兩位爲1,第三位爲0,則B爲兩個字節表示的字符中的第一個字節;
  • 若是B的前三位爲1,第四位爲0,則B爲三個字節表示的字符中的第一個字節;
  • 若是B的前四位爲1,第五位爲0,則B爲四個字節表示的字符中的第一個字節;

  所以,對於上面獲得的二進制串,每8位中的前面部分都是用來作標記的,1110開頭代表須要3個字節來描述當前字符,而且當前字節爲3字節中的第一部分,後面的字節使用10開頭代表本身是當前字符編碼串的後面部分。
  把前三字節這些標記爲去掉再合併,獲得 0110 110101 001011,而「」字的16進制Unicode編碼轉爲二進制,正是0110 1101 0100 1011。
  這樣作的優勢很明顯,擴展方便(看起來能支持到8字節編碼呢),編碼結構去掉了二進制的標記位,減少體積更易於數據傳輸。1字節的UTF-8碼還完整兼容了ASCII碼,因此UTF-8能夠說應該是大部分場景下的最優選擇了。測試

相關文章
相關標籤/搜索