在中文的語言環境裏,身爲程序員的咱們必定會遇到過中文亂碼的狀況,究其緣由就是字符編碼的問題。在沒有深刻理解其原理以前,會以爲中文編碼問題比較謎,莫名其妙地亂碼,又稀裏糊塗地好了。程序員
字符編碼是計算機技術的基石,本文但願幫助你們完全梳理清楚字符編碼問題,不只知其然,還知其因此然,擺脫被中文亂碼支配的感受。bash
在講解中文編碼問題以前,咱們須要先講講英語編碼,其解決方案是ASCII。網絡
ASCII的英文全稱是American Standard Code for Information Interchange,中文意思是美國信息交換標準代碼,是基於拉丁字母的一套計算機編碼系統,使用8位二進制表示字符。ui
在計算機內部,全部信息最終都是一個二進制值。每個二進制位(bit)有0和1兩種狀態,所以8個二進制位就能夠組合出256種狀態,這被稱爲一個字節(byte)。編碼
換句話說,一個字節能夠表示256種不一樣的狀態,每個狀態對應一個符號,也就是256個符號,從0000 0000到1111 1111,其數量計算公式:。spa
列舉一部分ASCII碼錶,以下所示:操作系統
二進制 | 十六進制 | 圖形 |
---|---|---|
0010 0000 | 20 | (space) |
0010 0001 | 21 | ! |
0011 0001 | 31 | 1 |
0011 1101 | 3D | = |
0100 0100 | 41 | A |
0110 0001 | 61 | a |
英語是由26個基本拉丁字母、阿拉伯數字和英式標點符號組成,所以用128個符號就足夠l了,但ASCII碼對於其餘一些複雜的語言,就力不從心了,好比:漢字大約將近10萬個(雖然沒有準確的數字,但平常使用漢字也有幾千字)。3d
一個字節只能表示256種符號,確定是不夠的,就必須使用多個字節表達一個符號。爲了正確顯示中文字符,在1981年5月1日,由中國國家標準總局發佈了《信息交換用漢字編碼字符·基本集》,一般簡稱GB。code
中國大陸幾乎全部的中文系統和國際化的軟件都支持GB2312。GB2312是簡體中文常見的編碼方式,使用兩個字節表示一個漢字,因此最多能夠表示個符號。orm
GB2312標準共收錄6763個漢字,其中一級漢字(經常使用字)3755個,二級漢字(較不經常使用)3008個,同時收錄了包括拉丁字母、希臘字母、日文平假名及片假名字母、俄語西裏爾字母在內的682個字符。
GB2312基本知足了計算機處理簡體漢字的需求,所收錄的漢字覆蓋了99.75%的使用頻率,但對於罕見字和繁體字,GB2312就不能處理了。所以發明了後來的GBK和GB18030。
它們之間的關係以下圖所示:
GBK編碼是GB2312編碼的超集,向下徹底兼容GB2312,兼容的含義是不只字符兼容,並且相同字符的編碼也相同。而GB18030編碼向下兼容GBK和GB2312,GB18030編碼是變長編碼。
但不少像GB類的編碼方式都有一個共同的問題,容許計算機處理雙語環境,即拉丁字母和本地語言,卻沒法同時支持多語言環境,即多種語言混合的狀況。Unicode就是爲了解決這個問題而誕生的方案。
世界上存在着多種語言,好比:西班牙語、韓語、俄語等等,它們也都分別有各自的編碼方式,因此同一個二進制數字能夠被解釋成不一樣的符號。若是想要正確的打開一個文本文件,就必須知道它的編碼方式,不然就會出現亂碼。
假若有一種編碼,將世界上全部的符號都歸入其中。每個符號都給予一個獨一無二的編碼,那麼亂碼問題就會消失。這就是Unicode,一種全部符號的編碼。
Unicode伴隨着通用字符集的標準而發展,當前最新的版本爲2019年5月公佈的12.1.0,已經收錄超過13萬個字符。Unicode涵蓋的數據除了視覺上的字形、編碼方式、標準的字符編碼外,還包含了字符特性,如大小寫字母。
然而,Unicode只是一個符號集,不表明計算機裏的編碼,它只規定了符號的二進制代碼,卻沒有規定這個二進制代碼應該如何存儲。
所以,致使了兩個問題:
隨着互聯網的發展,不一樣國家的信息愈來愈多地在網絡中傳播,強烈須要一種統一的編碼方式,UTF-8就是在互聯網上被普遍使用的一種Unicode實現方式。
再次強調一下,UTF-8是Unicode的實現方式之一,並非惟一,也不等同於Unicode。除了UTF-8,還有UTF-16和UTF-32,只是不多被使用。
UTF-8的特色是對不一樣範圍的字符使用不一樣長度的編碼,它可使用1~4個字節表示一個符號,根據不一樣的符號而變化字節長度。
其編碼規則很簡單:
Unicode與UTF-8的字節對應關係:
Unicode範圍 | UTF-8 |
---|---|
U+0000~U+007F | 0xxxxxxx |
U+0080~U+07FF | 110xxxxx 10xxxxxx |
U+0800~U+FFFF | 1110xxxx 10xxxxxx 10xxxxxx |
U+010000~U+10FFFF | 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx |
以「愛」爲例,其的Unicode是U+7231,是在U+0800~U+FFFF範圍內,因此採用3個字節進行編碼,其二進制爲01110010 00110001。
那麼用UTF-8表示,則以下圖所示:
計算機操做系統中的編碼:
若是使用的是Linux系統,能夠經過以下命令,查看系統中文編碼:
echo $LANG
en_US.UTF-8
複製代碼
若是想要查看文件的原始編碼,而且轉換編碼,可使用enca
命令,能夠經過apt-get install enca
進行安裝。
enca -L zh_CN <file> # 查看文件的編碼
enca -L zh_CN -x UTF-8 <file> # 將文件編碼轉換爲UTF-8編碼
enca -L zh_CN -x UTF-8 <file_1> <file_2> # 保留原始文件
複製代碼
字符編碼選擇建議:
最後,安利你們一本我寫的掘金小冊《深刻理解NLP的中文分詞:從原理到實踐》,讓你從零開始掌握中文分詞技術,踏入NLP的大門。若是以上內容對你有所幫助,但願你可以點贊、轉發、評論,多謝多謝!