1. 程式人生 > >【Python學習】字元編碼

【Python學習】字元編碼

先說兩個基礎知識。

(1)計算機內部,資料是由0,1組成的;

(2)計算機最小的資料單位,就是一個二進位制單位即bit,接下來就是8個二進位制單位表示一個位元組(Byte)。

1 ASCII碼

ASCII碼(American Standard Code for Information Interchange,美國資訊交換標準)只能用0,1表示26個字母(大小寫共計52個),阿拉伯資料(10個),還有一些標點符號、運算子號以及控制符(如換行,回車等)。

如果需要非常清楚的知道對應規則,可以查閱ASCII碼錶

需要表示的不多,所以僅拿出7位數字(0-127)來表示字元,這叫做基礎ASCII碼。剩下的(128-255)則留作擴充套件用。這也就意味著基礎ASCII碼位元組的最高位永遠是0

在Python裡可以看一下。

print('a') #列印字母a
print(ord('a')) #打印出字母a的ASCII碼十進位制
print(bin(ord('a'))) #打印出字母a的ASCII碼二進位制

輸出結果

a
97
0b110 0001  #0b表示是二進位制,最高位是0,但python輸出自動省略了

2 多位元組字元編碼(MBCS)——以中文為例

表示漢字的話,ASCII碼就不夠用了,那麼就拿多個位元組來表示。不同國家語言文字的編碼都要遵守一個共同的法則,就是要對ASCII碼保持向下相容。

也就是,最核心的就是原來ASCII碼最高位為0,那麼如果仍然是英文字母,這個最高位就還是0,而不是英文字母,這個最高位就變成1。

2.1 GB2312

以我們中文而論,我們國家在 1981 年釋出了簡體中文漢字編碼國家標準,也稱為 GB2312。

它的大致思想是使用1個94*94 的矩陣將所有字元儲存起來。行稱為區,列成為位。而中文字元也按照常用程度分為一級漢字和二級漢字。每一箇中文字元都是用區位元組和位位元組來表示的。為了和 ASCII 碼相容,作了如下規定:一個小於 127 字元的意義與原來ASCII 碼相同,但兩個大於 127 的字元連在一起就表示的是一個漢字。一個漢字。這樣實際上就足夠有214 = 16384種表示方法,這個數字不僅能夠涵蓋絕大部分的中文簡體字,還可以把數學符號,羅馬希臘字母以及日本的假名都編進去,甚至原來在ASCII 碼裡的數字、標點和字母也編了進去。但是這些數字和字母和原來 ASCII 碼不同的是它是用兩個位元組表示的,因此稱作全形

符號,而原來的 ASCII 碼字元則還稱作半形符號。


GB2312編碼對所收錄字元進行了“分割槽”處理,共94個區,每區含有94個位,共8836個碼位。這種表示方式也稱為區位碼。
01-09區收錄除漢字外的682個字元。
10-15區為空白區,沒有使用。
16-55區收錄3755個一級漢字,按拼音排序。
56-87區收錄3008個二級漢字,按部首/筆畫排序。
88-94區為空白區,沒有使用。
舉例來說,“啊”字是GB2312編碼中的第一個漢字,它位於16區的01位,所以它的區位碼就是1601。

具體的可以參看這個網站GB2312編碼


但由於要和 ASCII 碼相容,無論區碼還是位碼都要最高位為1。理論上我們只需要將每個碼加上128(十六進位制表示0x80),但是GB2312規定的是每個碼加上160(十六進位制表示0xa0)。這樣“啊”在計算機裡真正的儲存為0xb0,0xa1。

1544253512864

2.2 GBK

但是GB2312實際上只收錄了6763 個漢字,對於絕大部分應用是夠了。但是對於特殊字就不好辦了。還有就是臺灣人民所使用的繁體字(big5編碼),也不支援。

原來 GB2312 規定兩個位元組最高位都不能是1,而 GBK 規定首位元組的最高位為1,我們就認為後面是兩個位元組來表示漢字,而第2個位元組的最高位可以不是1。於是乎就大大擴充套件了編碼範圍,這一次收錄了21003個漢字,而且將繁體字也納入進來。

2.3 BIG5

1984年,臺灣五大廠商巨集碁、神通、佳佳、零壹以及大眾一同制定了一種繁體中文編碼方案,因其來源被稱為五大碼,英文寫作Big5,後來按英文翻譯回漢字後,普遍被稱為大五碼。目前,Big5編碼在臺灣、香港、澳門及其他海外華人中普遍使用,成為了繁體中文編碼的事實標準。由於Big5編碼和GB2312編碼是衝突的,因此一個文字內不可能既支援BIG5,也支援GB2312。實際上雖然GBK可以支援繁體中文,但是它和BIG5編碼也是相互衝突,並不相容的。

2.4 CodePage, MBCS, DBCS和ANSI

不僅僅中文如此,日文、韓文以及其他國家的文字也都是如此。因此這一類我們稱之為多位元組字元編碼(MBCS),但是由於實際上都是兩個位元組,因此有的時候我們也將其稱之為雙位元組字元編碼(DBCS)。微軟也將其稱之為美國國家標準(ANSI),所以我們在使用操作windows系統的記事本的時候,在另存時選擇字元編碼為ANSI,如果你是簡體中文作業系統,其實就是GBK,而如果是繁體作業系統的話,則是BIG5編碼。IBM為了統一各國字元編碼系統,他把所有的編碼編成了一本厚厚的“書”,中文的GBK編碼在936頁,因此也稱之為CodePage-936,而BIG5在950頁,也稱之為CodePage-950。

CodePage,MBCS,DBCS和ANSI這四個概念,其實是同一個意思,它們均不特指某一個字元編碼,而是在不同的地區和國家包括特定的含義。

3 統一字元編碼(Unicode, UTF-8)

最早的Unicode編碼是通過兩個位元組來進行編碼,但是我們已經知道兩個位元組最多隻能有\(2^{16}=65,536\)種表示方法,這個用來表示基於字母的語言是夠用的,但是對於類似中文、韓文、日文這樣的文字,那麼這個編碼還不夠。於是Unicode拿出了四個位元組來進行儲存。第1個位元組稱之為組,第2個位元組稱之為面,第3個位元組稱之為行,第4個位元組稱之為點。其中第0組,第0個面,會涵蓋絕大部分我們所使用的文字,因此也稱之為基本多語種平面(Basic Multilingual Plane)。

實際上,我們現在僅用了17個平面(從平面0-平面16)來儲存全世界所有的文字,這樣實際上是總共用了\(65,536×17=1114112\)個碼位。也就是說全世界所有的文字都能夠在0-1114111當中找到,這裡麵包括了71226個漢字。

規定了這所有文字的編碼後,接下來面臨的一個問題就是如何將這些文字編碼以位元組的形式表示在計算機裡,這個過程我們也稱之為Encoding過程。

於是出現了各種編碼轉換方法(Universal Transformation Formats),而最為著名的就是UTF-8。這個也促成了Unicode編碼和計算機儲存的分離。UTF-8的編碼原則有以下2條:

  • 如果一個字元的Unicode編碼小於128,這用一個位元組表示,保證了相容ASCII碼;
  • 如果一個字元大於128,這按照如下表規則編碼成2、3或者4個位元組。

1544254164011

【參考】

[1]《爬蟲基礎知識之字元編碼(以Python為例)》網際網路空間資料探勘研究小組

[2] GB2312編碼表