1. 程式人生 > >中文字元編碼的相互轉換(一)

中文字元編碼的相互轉換(一)

作為程式設計師,在日常的工作中總會遇到編碼的知識。尤其是在前後臺互動的過程中,字元編碼如影隨行。如果多個平臺的字元編碼不一致,需要相互轉化的話,很有必要了解一下編碼的工作原理。

網上有太多關於編碼的知識了,在此我儘量按照我對編碼的理解描述的簡單易懂。

1,ASCII碼

在計算機內部,所有的資訊最終都表示為一個二進位制的字串。每一個二進位制位是一個bit,有0和1兩種狀態。8個bit構成一個位元組,也就是byte。這就是bit和byte的區別。

在日常使用中,儲存的單位一般是byte,比如說到一個檔案大小是2k,是說這個檔案佔用了2048個byte;一個記憶體條的容量為256M,說明該記憶體可以儲存256*1024*1024個byte。網路傳輸的單位是bit,我們平常說到網路下行頻寬1M,是說此網路在最好的情況下可以同時下載速度是每秒1024*1024個bit,換算成位元組的話就是128k/s。


0和1各代表一個狀態,一個byte有8個bit,總共可以表示2的8次方=256個狀態。若是每個狀態對應一個符號,一個byte可以表示256個符號,也就是從0000000到11111111。

在上個世紀60年代,美國製定了一套字元編碼,對英語字元與二進位制位之間的關係,做了統一規定。這就是大名鼎鼎的ASCII碼了,一直沿用至今。此後雖然出現了各種各樣的編碼,但基本上都是相容ASCII碼的。

但ASCII碼一共只規定了128個字元的編碼,比如空格"SPACE"是32(二進位制00100000),大寫的字母A是65(二進位制01000001)。這128個符號(包括32個不能打印出來的控制符號),只佔用了一個位元組的後面7位,最前面的1位統一規定為0。


2,GB2312

英語用128個符號編碼就夠了,但是用來表示其他語言,128個符號是不夠的。我們就以中文做例子,中國的漢字有10萬左右,即使是常用字也有六七千,必須得用多個位元組來表示。

最先誕生的是GB2312編碼。其編碼結構不用特別瞭解清楚,感興趣的可以去網上搜索專門的文件。我們只需要明白以下幾點:
1)該編碼可以表示大概7000左右個字元。其中有中文及一些常見的拉丁字母等。基本可以覆蓋我們日常打字使用。
2)該編碼完全相容ASCII碼,計算機去讀的時候首先判斷最高位,如果是0,那麼這個字元只佔用一個位元組,表示的內容跟ASCII碼錶示的一樣。如果該字元最高位是1,那麼該位元組連同下一個位元組表示一箇中文漢字。所以平常咱們常說的英文一個位元組,中文兩個位元組其實是從這裡來的。


3,GBK

兩個位元組最多可以表示的字元數是 2的16次方=65536,如果要求首位必須是1,那麼最多可以表示 32768 個字元,但是GB2312 只用了其中的7000左右的字元。這顯然是沒有做到物盡其用,而且如果有些特殊的中文,GB2312根本表示不了。所以GBK就應運而生了。

GBK 就儘量將能用到的狀態都表示成中文字元了,當然最終還是有些狀態沒辦法用(具體可以自行查詢文件),最終可以表示23940個字元,其中有21003是漢字。

GBK是完全相容GB2312的,所以GBK的應用是很廣泛的,而且從Windows95開始,Windows的中文版預設中文支援就是GBK編碼。

4,Unicode

GBK基本解決了中文編碼問題,但另外一個大問題隨之而來,那就是國際化。咱們按照此方式來表示簡體中文,繁體中文怎麼表示?日本和韓國他們的文字也沒法弄。當然他們也利用最高位來做文章,發明了big5等相容ASCII碼的編碼格式,但是這幾種編碼之間是並不相容的。一段GBK編碼的檔案在臺灣友人的電腦裡開啟就是亂碼了。

這時候,Unicode就誕生了。

完全弄明白Unicode的細節是非常困難的,我們也是明白以下幾點就夠了:
1)Unicode編碼是給世界上所有的符號都分配了一個碼。GBK最多也只能表示3萬多的漢字,康熙字典裡面的大部分漢字都沒法用GBK表示,但是Unicode就能,它可以表示這個星球上所有的符號。
2)Unicode有UCS-2和UCS-4兩種編碼,2和4都是代表位元組的意思,也就是說前者用兩個位元組表示,後者用4個位元組表示。所以,UCS-2的表示範圍是65536個字元,而UCS-4則可以表示超過22億個字元,我想這真的是可以表示所有的字元了。其實日常使用我們用的只是UCS-2,一般說的Unicode編碼也是隻它。它包含了所有的簡體中文,現用的繁體中文,火星文,以及其他國家的現用文字。古籍中的文字就得去UCS-4中去找了。

5,UTF-8

很遺憾,Unicode並不是完美的。不完美的地方主要有兩點:
1)不相容ASCII碼。因為Unicode是用兩個位元組表示,ASCII碼範圍內的字元都被擴充成了兩個位元組,前面又補了8個0。所以,如果你的電腦只支援Unicode編碼的話,所有的英文資料全都沒法閱讀了。
2)佔用的儲存變大,如果涉及到傳輸,所耗費的流量也會變大。中文的表現一般,英文表現最明顯。純英文文字所消耗的儲存比以前增大了一倍。

這個時候就出現了諸如UTF-8等實現方式。這裡我們只討論UTF-8,因為它是使用最廣泛的。它彌補了Unicode的缺陷,所以一誕生就風靡全球了。UTF-8主要有以下幾個優點。
1)UTF-8與Unicode是一一對應的。所以UTF-8是國際化的編碼方式。
2)UTF-8是針對Unicode的可變長度字元編碼,最短一個位元組,最長3個位元組,1個位元組表示的就是ASCII碼,所以UTF-8是完全相容ASCII碼的。
3)正是因為UTF-8的變長實現,解決了Unicode的儲存多的問題。可能有朋友要問了,UTF-8最多需要用3個位元組表示,而Unicode只需要兩個,怎麼能說UFT-8會省儲存呢?因為目前英文是最通用的語言,大部分字元都是ASCII碼。

但UTF-8並不是一點缺點也沒有,因為變長表示,所以一段UTF-8編碼沒法一下子算出有多少個字元。而這一點能力對於以上幾種編碼格式來說是輕而易舉的。所以當今世界上沒有最完美的字元編碼,只有最合適某個場景的編碼。