常用編碼
在計算機世界,所有信息都是用二進制存儲。每一個二進制有0和1兩種狀態。
所以8個二進制就可以組合成256種狀態,也就是一個字節。
也就是說,一個字節可以用來表示256種不同的狀態,每一個狀態對應一個符號,也就是256個符號,從00000000—11111111。
ASCII碼
一共規定了128個字符的編碼,包含大小寫字母、數字、還有空格等一些常用符號,這128個符號中有32個不能打印出來的控制符號。只占用了一個字節的后面7位,也就是最前面一位都是0.
大寫字母A是65,也就是二進制的01000001。
空格是32,也就是二進制的00100000。
非ASCII編碼
上面講的ASCII編碼規定的128個字符,對英語來說足夠用了,但是用來表示其他語言,128個符號不夠用。例如,法語字母上面有注音符號,它就無法用ASCII碼表示。於是,一些歐洲國家就決定,利用字節中閑置的最高位編入新的符號。
比如,法語的é的編碼為130,二進制位10000010,這樣以來歐洲國家可以使用8個二進制的所有組合,也就是最多256個符號。
但是,這也有問題,130在法語編碼中表示é,而在希伯來語編碼中卻代表字母Gimel(ג),在俄語編碼中又代表另一個符號。但是不管怎樣,所有這些編碼方式中,0—127表示的符號是不一樣的,不一樣的只是128—255的這一段。
至於亞洲國家的文字,額….漢字就10W+,256種符號肯定不夠,就必須使用多個字節表達一個符號。比如,簡體中文常見的編碼方式是GB2312,使用256個字節表示一個漢字,所以理論上最多表示256*256=65536個符號。
當然,世界上的編碼方式有很多,不止上面提到的這些。
Unicode
世界上存在着多種編碼方式,同一個二進制數字可以被解釋不同的符號。因此,要想打開一個文本文件,就必須知道它的編碼方式,否則用錯誤的編碼方式解讀,就會出現亂碼。
Unicode是一種把世界上所有符號都納入其中,每一個符號都給予了一個獨一無二的編碼,那么亂碼問題就會消失。
Unicode是一個很大的集合,現在的規模可以容納100多萬個符號,每個符號的編碼都不一樣,比如:
U+0639表示阿拉伯字母Ain。
U+0041表示英語的大寫字母A
U+4E25 表示漢字嚴
Unicode的問題
Unicode只規定了符號的二進制代碼,卻沒有規定這個二進制代碼應該如何存儲。
例如:漢字嚴轉化為二進制是100111000100101,足足有15位,也就是最少需要兩個字節,甚至有更大的符號,需要3個字節或者4個字節,甚至更多。
這就有了兩個嚴重的問題:
1.如何區分Unicode和ASCII,計算機怎么知道三個字節表示一個符號,而不是表示三個符號呢?
2.我們已經知道英文字母只用一個字節表示就足夠了,如果Unicode同一規定,每個符號用三個或四個字節表示,那么每個英文字母前都必須有2—3個字節是0,這對於數據存儲來說是極大的浪費,文本文件的大小因此會打出2—3倍,這是無法接受的。
UTF-8閃亮登場
UTF-8是Unicode的一種實現方式,其他實現方式還有UTF-16(字符用2—4個字節表示),UTF-32(字符用四個字節表示),不過其他的在互聯網上基本不用,UTF-8就是為了統一編碼方式產生的,也是互聯網上使用最廣的一種Unicode的實現方式。
UTF-8的最大特點,就是它是一種邊長的編碼方式,可以使用1—4個字節來表示一個符號,根據不同的符號而變化字節長度。
它的規則很簡單,只有兩條:
對於單字節的符號,字節的第一位為0,后面7位為這個符號的Unicode碼。因此,對於英文字母,UTF-8和ASCII碼是相同的。
對於n字節的符號(n>1),第一個字節的前n位都設為1,第n+1位設為0,后面字節的前兩位一律為10。
漢字嚴的Unicode是4E25(100111000100101),需要用三個字節存儲,根據上面的規則,即格式為:
1110xxxx 10xxxxxx 10xxxxxx
記住,二進制是從后往前存儲的,讀也是從后往前讀的,所以我們先填充第三個字節,從二進制的后面讀取,填充完后變成了:
1110xxxx 10xxxxxx 10100101
再根據同樣規則填充第二個字節,填充完后變成了:
1110xxxx 10111000 10100101
最后填充最后一個字節:
1110x100 10111000 10100101
不對啊,怎么少了一個字節?沒事,少了的用0補位:
11100100 10111000 10100101
Unicode與UTF-8的轉換
這兩種編碼的轉換可以通過程序實現,在Windows平台下,最簡單的方法是,通過記事本另存為:
ACSI就是ACSII,是Windows英文系統的默認的編碼格式,但是對於Windows簡體中文版默認就是GB2312,針對繁體中文版默認就是Big5。
而現顯示的Unicode都是使用UCS-2編碼方式存儲的Unicode字節,只不過默認是little endian格式,而另一個選項是Unicode big endian格式。
Unicode little endian與Unicode big endian的轉換:
簡單舉個例子,UCS-2格式可以存儲Unicode碼。漢字嚴的Unicode碼為4E25,需要用兩個字節存儲,一個字節是4E,另一個是25。4E在前,25在后就是Big endian(從前往后),25在前,4E在后,就是Little endian(從后往前)。
那計算機怎么知道某一個文件到底采用哪一種方式編碼呢?
Unicode規范定義,每一個文件最前面分別加入一個表示編碼順序的字符,這個字符的名字叫做 “zero width no-break space” ,用FEFF表示,正好是兩個字節。
如果一個文本文件的頭兩個字節是FE FF,表示是Big endian方式,如果頭兩個字節是FF FE,表示是Little endian方式。
本文大部分來自阮一峰大神的個人博客:http://www.ruanyifeng.com/blog/2007/10/ascii_unicode_and_utf-8.html