網站開發中常常會被亂碼問題困擾。知道文件編碼錯誤會致使亂碼,但對其中的原理卻知之甚少。偶然從某篇文章瞭解了Unicode,發現從這條線出發也牽引出了一系列缺失的知識點。經過研讀文章,基本瞭解了一些之前不明白的問題,因此整理了幾篇,從幾個角度介紹下Unicode, 並聊聊一些相關的問題。html
上世紀60年代,美國人採用了一種編碼來表示英語以及各類符號,該編碼方式只有一個字節,能表示256(2^8)個字符。至今爲止才定義了128個字符。包括33個控制字符和95個可顯示字符,這些可顯示字符涵蓋了大小寫英文字母和一些符號,這就是大名鼎鼎的ASCII編碼。瀏覽器
然而隨着計算機的發展,各個國家的語言符號多不勝數,在中國光中文字符就有7000多個,還不包括繁體中文,ASCII顯然沒法知足這麼多字符編碼需求。因此中國人本身創造了一種字符編碼,每一個漢字和符號用兩個字節來表示。第一個字節稱爲"高位字節",第二個字節稱爲"低位字節"。高位字節使用了0xA1 - 0xF7, "低位字節"使用了0xA1 - 0xFE。同時該編碼方式兼容了ASCII的編碼,對於小於127的字符即0x00 - 0x7F的字符予以保留。這種編碼方式就是中文編碼GB 2312。網站
然而GB 2312能表示的文字也比較有限,對於一些人名,古漢語和繁體字也無能爲力。因此咱們改進了GB 2312的編碼方式,擴展了GB 2312 中不使用的字節,使其同時包括了GB2312的全部內容,又新增了近20000個新的漢字,包括繁體字。該編碼就是咱們熟悉的GBK。後來因爲又加了少數名族的文字,又推出了GB18030,用於取代GBK。而目前爲止咱們使用最普遍的中文編碼仍是GBK。編碼
再後來,因爲不一樣的國家地區之間都使用不一樣的編碼,致使計算機文件的讀取都須要安裝不一樣的解碼軟件。常常照成文件讀取亂碼。因而有一些組織決定製定出一個方案,經過統一的編碼解決這個難題。因而其中一個團隊發明了UCS編碼,還有另外一個團隊發明了Unicode。後來二者達成一致,只發布一套字符集,那就是Unicode 。而UCS的碼點將與Unicode保持一致。spa
Unicode最初規定用16位的編碼空間,這16位編碼空間稱爲統一碼。這樣理論上一共最多有2^16(65536)個字符。基本知足各類語言的使用。實際上當前版本的統一碼並未徹底使用這16位編碼,而是保留了大量空間以做爲特殊使用或未來擴展。設計
目前的Unicode字符分爲17組編排,每組稱爲一個平面(Plane),而每平面擁有65536(即2^16)個碼點。上述16位統一碼字符稱爲基本多文種平面(BMP),寫成16進制就是從U+0000到U+FFFF。 剩下還有16個輔助平面(SMP),碼點範圍從U+010000一直到U+10FFFF。這17個平面結合起來至少須要佔據21位的空間(2^16 x 2^5),也就是差很少3個字節(24位),而輔助平面其實是用4個字節表示,方便之後向後擴展。code
上面講到的幾種編碼都是編碼方式,規定了從碼點到字符的映射關係,例如 Unicode中U+0061 對應的就是小寫字母 "a", 咱們能夠在瀏覽器控制檯中輸入碼點查找對應的字符:orm
UTF
Unicode的實現方式不一樣於編碼方式。一個字符的Unicode編碼是肯定的。可是在實際傳輸過程當中,因爲不一樣系統平臺的設計不必定一致,以及出於節省空間的目的,對Unicode編碼的實現方式有所不一樣。Unicode的實現方式稱爲Unicode轉換格式(Unicode Transformation Format,簡稱爲UTF)。htm
網頁開發中比較熟悉和經常使用的編碼實現是UTF-8。那麼這種實現方式有什麼優點呢?UTF-8是一種變長的編碼方法。字符長度從1字節到4字節不等。最前面的128個字符,只使用1個字節表示,延續了ASCII的用法。其餘分段的字節數以下:blog
計算機在讀取數據的時候都是從高位到地位或從地位到高位。當計算機讀到一個3字節字符時,怎麼判斷是輸出1位字符,仍是繼續讀取接下來的2位併合併爲一個字符呢?這就要涉及到UTF-8的具體實現了。
UTF-8是這樣作的:
單字節的字符,字節的第一位設爲0,對於英語文本,UTF-8碼只佔用一個字節,和ASCII碼徹底相同;
n個字節的字符(n>1),第一個字節的前n位設爲1,第n+1位設爲0,後面字節的前兩位都設爲10,這n個字節的其他空位填充該字符unicode碼,高位用0補足。
這樣就造成了以下的UTF-8標記位:
0xxxxxxx
110xxxxx 10xxxxxx
1110xxxx 10xxxxxx 10xxxxxx
11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
當讀到第一位時,發現是0開頭,就讀一個字節。發現是110,就讀兩個字節,發現是1110就讀三個字節,以此類推,再根據Unicode規則找到對應的符號輸出。這種變長的編碼方式,能根據字符采用不一樣位數的碼點,可以有效減小文件的體積。
若是採用Unicode的編碼方式直接做爲實現方法。那麼每一個字符都是定長的碼點,對於只須要一個字節的字符,須要在前面補0. 這樣就照成了空間的浪費,文件就會變大。
UTF編碼除了UTF-8,還有UTF-16:最小的碼點爲2個字節;UTF-32:每一個碼點固定用4個字節表示。因爲UTF-32傳輸場進下會照成文件空間浪費,HTML5標準規定,網頁不得編碼成UTF-32。
關於Unicode的介紹就到這。UCS的相關知識,將在下一章結合JavaScript一塊兒講到。
參考文章:
https://zh.wikipedia.org/wiki
http://www.ruanyifeng.com/blo...
https://www.zhihu.com/questio...