從一個問題提及算法
爲何計算字符串的長度的時候會把中文當作2個字符,英文當成一個字符來計算?數組
在計算機中,字符是一個信息單位。簡單來講就是一個漢字或者一個英文,一個標點符號。網絡
顧名思義,字符集就是字符的集合。編碼
字符編碼就是把字符集中的字符編碼爲指定集合中的某一對象,以便在計算機中存儲和經過網絡傳遞。3d
是指一個已編碼的文本中具備最短比特組合的單元。對於UTF-8來講碼元是8比特長。對於UTF-16來講,碼元是16比特長。對於UTF-32來講,碼元是32比特長。代理
字符編碼由如下幾個關鍵元素構成:code
全稱是American Standard Code for Information Interchange,譯作美國信息交換標準代碼。這套字符集在1967年被正式公佈。orm
它一共包含128種字符,其中33個控制字符,95個可顯示的字符。正好是一個字節的低7位,最高位置0。cdn
下圖是一個ASCII碼的表格: 對象
剛開始計算機只在美國使用,因此128個字符是夠用的,可是隨着科技的發展歐洲的國家也開始使用上了計算機。這時候出現了問題,128個字符不夠用了。好比法語中有注音符號,因而一些歐洲國家決定利用字節中閒置的最高位編入新的符號。 這樣就在ASCII碼的基礎上,既保證了對ASCII碼的兼容性,又補充擴展了新的字符,因而就稱之爲Extended ASCII(擴展ASCII)碼,簡稱EASCII碼。
在EASCII碼中,當第一個比特位(即字節的最高位)爲0時,仍表示以前那些經常使用的ASCII字符(實際的二進制編碼爲0000 0000 ~ 0111 1111,對應的十進制就是0~127),而爲1時就表示補充擴展的其餘衍生字符(實際的二進制編碼爲1000 0000 ~ 1111 1111,對應的十進制就是128~255)。
EASCII的擴展部分以下圖: [image:DA4EFEE5-575B-4D69-AB85-0D6A0963052E-55654-00029E64D82D4B45/18408A67-1AF3-4473-AE8A-E7E6DE1C355B.png]
可是有這樣想法的國家有不少,因此還有另外一套標準就是ISO 8859。
ISO 8859 是一組字符集的總稱,其下共包含了15個字符集,即ISO 8859-n ,其中n=1,2,3…11,13,14,15,16
這兩種編碼方式都是前128位兼容ASCII碼,後128位本身定義。
後來計算機進入了中國,EASCII碼也不夠用了。要知道,漢字是世界上包含符號最多的文字。因而⌈中國國家標準總局⌋(現已改名爲⌈國家標準化管理委員會⌋)在1981年,正式制訂了中華人民共和國國家標準簡體中文字符集,全稱《信息交換用漢字編碼字符集·基本集》,項目代號爲GB 2312 或 GB 2312-80(GB爲國標漢語拼音的首字母),此套字符集於當年的5月1日起正式實施。
GB2312編碼爲了不與ASCII字符編碼(0~127)相沖突,規定表示一個漢字的編碼(即漢字內碼)的字節其值必須大於127(即字節的最高位爲1),而且必須是兩個大於127的字節連在一塊兒來共同表示一個漢字(GB2312爲雙字節編碼),前一字節稱爲高字節,後一字節稱爲低字節;而一個字節的值若小於127(即字節的最高位爲0),天然是仍表示一個原來的ASCII字符(ASCII爲單字節編碼)。
所以,能夠認爲GB2312是對ASCII的中文擴展(即GB2312與ASCII相兼容),正如EASCII是對ASCII的歐洲文字擴展同樣。
不過,很顯然的是,GB2312與EASCII碼的128~255這段擴展部分所表示的字符是不一樣的。也就是說,GB2312與EASCII雖然都兼容ASCII,但GB2312並不兼容EASCII的擴展部分。
事實上,目前世界上除ASCII以外的其它通行的字符編碼方案,基本上都兼容ASCII,但相互之間並不兼容。
GB2312中,多是出於顯示上視覺美觀的考慮,除漢字以外的682個字符中,甚至包括了ASCII裏原本就有的數字、標點、字母等字符。也就是說,這些ASCII裏原來就有的單字節編碼的字符,又再編了兩個字節長的GB2312編碼版本。這682個字符就是常說的「全角」字符,而這682個字符中所對應的ASCII字符就被稱之爲「半角」字符。
上面說了這麼多種編碼,每一個國家都有本身的編碼標準,以便能在計算機上正確的顯示本身國家的符號。可是不一樣國家地區互相不能正確顯示。因此有2個組織來嘗試指定統一的編碼標準。
1991年,兩個組織共同的工做成果Unicode 1.0正式發佈,不過Unicode 1.0並不包含CJK字符(即中日韓)。
1993年時,包含CJK的Unicode 1.1已經發布了,因而在同一年,中國大陸制定了幾乎等同於Unicode1.1的GB13000.1-93國家編碼標準(簡稱GB13000)。是的,你沒聽錯,中華人民共和國信息產業部把Unicode裏的全部東東拿過來,而後本身從新修訂發佈了下,改成了國家標準GB13000。此標準等同於 ISO/IEC 10646.1:1993和Unicode 1.1。
GB2312 基本覆蓋了中國大陸99%以上的使用頻率,基本知足了漢字的計算機處理須要。但對人名,生僻字等並不能處理。
因而,利用GB2312未使用的碼點空間,收錄這些字符,於1995年又發佈了《漢字內碼擴展規範(GBK)》。其中K是擴展的意思。
GBK跟GB2312同樣是雙字節編碼,然而,GBK只要求第一個字節即高字節是大於127就固定表示這是一個漢字的開始(0~127固然表示的仍是ASCII字符),再也不要求第二個字節即低字節也必須是127號以後的編碼。這樣,做爲一樣是雙字節編碼的GBK才能夠收錄比GB2312更多字符。
因此GB系列的編碼方案中,一個漢字是由2個字節組成,一個英文是由一個字節組成。
顧名思義,UCS-2就是用兩個字節編碼,UCS-4就是用4個字節(實際上只用了31位,最高位必須爲0)編碼
是Unicode的一種實現方式。是一種可變長度的編碼方式。它可使用1~4個字節表示一個符號,根據不一樣的符號來變化字節長度。 編碼規則:
編碼實現:
根據編碼規則,同理能夠推出解碼規則:
舉個例子: 0xxxxxxx 110xxxxx 10xxxxxx 1110xxxx 10xxxxxx 10xxxxxx 1110xxx 10xxxxxx 10xxxxxx 10xxxxxx
也是Unicode的一種實現方式。是把Unicode字符集的抽象碼位映射爲16位長的整數(碼元)的序列。須要1~2個16位長的碼元來表示,因此這是一個邊長表示。
Unicode的編碼空間從U+0000到U+10FFFF,共有1,112,064個碼位(code point)可用來映射字符。Unicode的編碼空間能夠劃分爲17個平面(Plane),每一個平面包含2^16(65536)個碼位。17個平面的碼位可表示爲從U+xx0000 到 U+xxFFFF,其中xx表示十六進制從00到10。第一個平面稱爲基本多語言平面(Basic Multilingual Plane, BMP),或稱第零平面(Plane 0)。其餘平面稱爲輔助平面(Supplementary Planes)。基本多語言平面內,從U+D800到U+DFFF之間的碼位區塊是永久保留不映射到Unicode字符。UTF-16就利用保留下來的0xD800-0xDFFF區段的碼位來對輔助平面的字符的碼位進行編碼。
編碼規則: U+0000 ~ U+D7FF 和 U+E000 ~ U+FFFF 這個範圍即基本多語言平面(Basic Multilingual Plane, BMP),包含了最經常使用的字符,包含的碼位範圍是U+0000 到 U+FFFF,只須要一個16位的碼元便可表示。
U+10000 ~ U+10FFFF 其它平面(叫作輔助平面,Supplementary Planes)中的碼位,在UTF-16中被編碼爲一對16比特長的碼元(即32bit,4Bytes),稱做代理對(surrogate pair),具體方法是:
上述算法可理解爲:輔助平面中的碼位從U+10000到U+10FFFF,共計FFFFF個,即2^20=1,048,576個,須要20位來表示。若是用兩個16位長的整數組成的序列來表示,第一個整數(稱爲前導代理)要容納上述20位的前10位,第二個整數(稱爲後尾代理)容納上述20位的後10位。還要能根據16位整數的值直接判明屬於前導整數代理的值的範圍(2^10=1024),仍是後尾整數代理的值的範圍(也是2^10=1024)。所以,須要在基本多語言平面中保留不對應於Unicode字符的2048個碼位,就足以容納前導代理與後尾代理所須要的編碼空間。這對於基本多語言平面總計65536個碼位來講,僅佔3.125%.
編碼規則實現:
根據UTF-16的編碼規則,同理能夠獲得解碼規則,下圖是從Swift源碼中截取的UTF-16的解碼代碼: [image:69D26150-1CDC-4E9D-B94E-916136C27353-55654-0002535098FC388A/46208888-62B3-4137-95AE-A697AFD5B43A.png]
舉個例子: 例如U+10437編碼(𐐷)
UTF-16比起UTF-8,好處在於大部分字符都以固定長度(2字節)存儲,可是UTF-16沒法兼容ASCII碼。
思考問題:
一、Unicode與UTF-8 16 有什麼區別?
二、爲何UTF-8不須要專門指明字節序?
三、爲何計算字符個數會把英文當成一箇中文當成兩個?
四、咱們常說的Unicode編碼指的是什麼?