文檔保存格式UTF-8

ASCII碼:

     C語言中,一個字節對應八位二進制數,每一位二進制數就有0、1兩種狀態,所以一個字節有2^8=256種不同的狀態,美國人最早用一字節的數據表示256個字符,稱爲ASCII碼。ASCII定義了128個字符,也就是隻使用了8位二進制數的後七位,最前面的一位統一規定爲0



Unicode

問題:

 128個字符來編碼英文是完全足夠的,但是用來表示其他語言,128個字符是遠遠不夠的,即便用上閒置的最高位,不同國家的編碼會不一樣。最終,美國人意識到提出一種標準方案來展示世界上所有語言中的所有字符, unicode由此誕生了。

     Eg:

“漢”字在unicode碼點是0x6c49需要兩個字節來表示,轉化爲二進制數110110001001001就是他的編碼,但是問題又來了,當你譯碼時,比如看到的兩個字節,那它到底表示的是一個兩字節字符還是兩個一字節字符。

爲了解決這個編碼問題,編碼採用定長編碼,選字節的編碼方式,即4字節編碼。

 


UTF-8

這種情況下,編碼譯碼都能實現一對一,但是又出現了一點小bug:空間的浪費(字符不足四字節時,高位全部補零),所以我們能不能想一種辦法既能解決unicode的譯碼譯碼問題又不會浪費空間呢?UTF-8解決了這個問題。(既然譯碼時識別不出一個字節和多個字節的字符,那就在多字節字符上面做一些標誌位)

UTF-8可以根據字符的不能變換長度,使用1-4個字節表示一個字符。編碼規則如下:

[if !supportLists]1)  [endif]單個字節的字符,同unicode(向後兼容)

[if !supportLists]2)  [endif]對於需要N個字節來表示的字符(N > 1),第一個字節的前N位都設爲1,第N + 1位設爲0,剩餘的N – 1個字節的前兩位都設爲10,剩下的二進制位使用這個字符的unicode碼點來補充。如下:

Unicode 十六進制碼點              UTF-8二進制

00000 0000 – 0000 007F  2^4 + 2^3   0xxxxxxx                          2^7

00000 0080 – 0000 07FF  2^7 + 2^4   110xxxxx 10xxxxxx                 2^11

00000 0800 – 0000 FFFF  2^11 + 2^5  1110xxxx 10xxxxxx 10xxxxxx          2^16

00001 0000 – 0010 FFFF  2^16 + 2^5  11110xxx10xxxxxx 10xxxxxx 10xxxxxx   2^21

Eg:

“漢”字unicode的碼點0x6c49(2^4+2^4+2^4+2^3),原本只需要兩字節表示,高位補零即可。但是這裏添加了標誌位,對照上圖,需要三字節表示。

 格式是:1110xxxx 10xxxxxx 10xxxxxx

0x6c49轉爲二進制:110110001001001

從地位依次填充(高位補零):  11100110 10110001 10001001

轉爲十六進制(UTF-8):0xE6 B189

譯碼時:有多少個1就代表是多少個字節(N個後由一個0隔開)

 


UTF-16

平面的概念:unicode將全世界所有的字符定義在一個集合裏,這麼多字符不是一次性定義的,而是分區定義。每個區可以存放65535個(2^16)字符,稱爲一個平面。目前共使用了17(2^4+1)個平面。

基本平面的碼點範圍:0x0000-0xffff  ,都採用兩字節存儲,因此不兼容ASCII碼

輔助平面的碼點範圍:0x010000-0x10ffff<2^5>

編碼規定:

     基本平面佔用兩字節,輔助平面佔用四字節。

同樣的問題:

     譯碼時怎麼區分兩字節和四字節字符呢?

在這裏使用了另外一種方法:

在基本平面內設置了一個空段:0xD800-0xDFFF,這2^11空間分爲兩部分,D8000到    DBFF(共2^10空間)稱爲高位,DC00到DFFF稱爲底位,爲什麼要這麼稱呼呢?

UTF-16把超出基本平面部分的字節分高低位(高8位,底8位),然後分別映射(從地位開始複製,多餘位不動)到剛說的基本平面的空段的高低位(高位補零)

 Eg:

     漢子“?”的unicode碼點爲0x20BB7

基本平面存儲爲0xffff

超出部分爲0x20BB7-0x10000=10BB7

轉爲二進制:100001011 10110111

補齊20位:0001000010 1110110111

映射:

0001000010(高十位)-> 0XD800(1101101100000000)  :  1101100001000010轉十六進制:D842

 1110110111(底十位) ->0xDC00(1101110000000000)  :  1101111110110111轉十六進制:DFB7

得到漢字“?”的UTF-16編碼爲0xD842 0xDFB7


  輔助平面轉換公式:

   H = ( num– 0x10000) / 0x400) + 0xD800

   L = ( num– 0x10000) % 0x400) + 0xDC00


UTF-8是對多字符進行標記,不固定長度存儲從而節省空間

UTF-16,小於兩字節長度的字符固定兩字節長度存儲,超出就按四字節存儲,而四字節分爲高低位映射到前兩字節存儲,也就是隻用了兩字節空間




總結:

    Unicode是一種可以在計算機上使用的字符編碼,它爲每一種語言每一個字符都設定了一個二進制編碼,以滿足跨語言、跨平臺進行文本轉換、處理的要求。使用數字0-0x10FFFF映射字符,最多容納1114112個字符(的17個平面大小2^16*17,其中有已經使用的平面,也有備用平面或者給用戶自定義字符平面等)。

UTF-8、UTF-16、UTF-32是對Unicode字符集不同的編碼方式,比如漢字“字”在unicode中對應的數字是23383,把其按照不同的編碼方式轉換爲程序數據如下:(無符號)

UTF-8:0xE6,0xB1,0x89,0xAD,0x97

UTF-16:0x6C49,0x5B57

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章