ASCII、GB2312、GBK、GB18030、Unicode、UTF-8、BIG5 編碼分析詳解(全網最全)

ASCII、GB2312、GBK、GB18030、Unicode、UTF-8、BIG5 編碼詳解

當你打開一個文件,發現竟然亂碼了;當你下載了一個未引進的國外軟件,打開發現也亂碼了。

這是怎麼回事?

其實我們在生活中遇到的絕大多數亂碼問題,都是因爲不同的編碼字符集導致的。

甚至不少程序猿也深受編碼問題的困擾。

例如一個學習Python的新手在用Python2寫代碼時想輸出中文,程序肯定會報出 UnicodeDecodeError 這樣的錯誤。例如一個前端開發工程師寫了一個網頁用瀏覽器打開看到的都是些小方框。
事實上Python2不支持中文這個問題只需要在代碼中添加一行聲明編碼方式就解決了。一行代碼解決Python2不支持中文字符集

目前,我們比較常見的編碼規範有 ascii、gb2312、gbk、gb18030、unicode、utf-8、big5 這7種,它們收納了不同範圍的字符,如果你的文件中包含了某種編碼沒有收納的字符,打開當然會亂碼。

因此,深入瞭解編碼,弄懂他們的區別、應用場景以及相互間轉換的方式,我們將徹底擺脫編碼問題帶來的種種煩惱。下面,我將從計算機原理開始講清楚編碼的前世今生,並在最後對這幾種編碼進行總結對比。

一、什麼是編碼,爲什麼需要編碼

首先,我們從信息(消息)說起。消息以人類可以理解、易懂的表示存在,我們將這種表示稱爲“明文”(plain text)。比如我們能看懂的漢字、英文、圖片等都可以稱爲明文。

然而,計算機只認識二進制數字,計算機中的所有數據,不論是文字、圖片、視頻、還是音頻文件,本質上都是按照類似 01010101 的二進制存儲的,在我們的明文面前它相當於一個文盲。

爲了讓計算機表示我們能看懂的明文,我們需要將明文表示的消息轉成0101這種二進制表示,我們還需要將0101這種二進制表示轉回成明文。從明文到二進制的轉換稱爲“編碼”,從二進制文本又轉回成明文則爲“解碼”。

在這裏,順便簡單解釋下爲什麼計算機只懂二進制:
在計算機電路中,電平只有兩種狀態,高電平(通電)和低電平(未通電),並規定用1和0表示這兩種狀態。當多個電平組合在一起,就相當於對多個0、1進行排列組合,假設4個電平爲一組,那麼就可以表示 24 = 16種不同的狀態。

二、 ascii、gb2312、gbk、gb18030、unicode、utf-8、big5 編碼的產生和定義

1. ASCII 編碼:

定義:
ASCII(American Standard Code for Information Interchange,美國標準信息交換代碼)是基於拉丁字母的一套電腦編碼系統,主要用於顯示現代英語和其他西歐語言,其最多隻能用 8 位來表示(一個字節),即:28 = 256,所以,ASCII碼最多隻能表示 256 個符號。

誕生:
計算機只認二進制,如果將八個電平做爲一組就可以表示出 28 = 256種不同狀態,如果用不同的狀態來表示不同的字符,比如將字母“A”用00010001來表示,那麼8位電平一共就可以表示256種不同的字符,而英文字母只有26個字符,算上一些特殊符號和數字,其實只要128個狀態就已經能夠表示了。規定將每個電平稱爲一個比特位(bit),約定8個比特位構成一個字節(byte),這樣計算機就可以用127個不同字節來存儲英語的文字,於是ASCII編碼就。

擴展ascii碼:上面提到其實只要128種狀態就能表示所以英文字母和常見符號了,一個字節由8位二進制組成,一共可以表示256種字符,然而才利用一半,爲了不浪費,就把剩餘沒有利用的狀態用來表示拉丁文了,遺憾的是它並沒有表示漢字,所以初始的ascii編碼是不支持中文的。

下圖是ASCII編碼表示的前128種字符:ASCII有人可能會有疑惑了,爲什麼不用來表示漢字呢?
因爲ascii編碼裝不下那麼多漢字;最關鍵的是這是美國人發明的,對他們來講能編碼英文就足夠了,何況那時候中國還沒有幾臺計算機呢。

2. GB2312 編碼:

查看GB2312簡體中文編碼表

定義:
GB2312編碼是中華人民共和國國家漢字信息交換用編碼,全稱《信息交換用漢字編碼字符集——基本集》,由國家標準總局發佈,1981年5月1日實施,通行於大陸。新加坡等地也使用此編碼。GB2312 收錄簡化漢字及符號、字母、日文假名等共 7445 個圖形字符,其中漢字佔 6763 個。GB2312規定“對任意一個圖形字符都採用兩個字節表示,每個字節均採用七位編碼表示”,習慣上稱第一個字節爲“高字節”,第二個字節爲“低字節”。

誕生:
當計算機漂洋過海來到中國後,問題來了,計算機不認識中文,當然也沒法顯示中文;而之前的ascii編碼又沒有收錄漢字,而且一個字節的256種狀態都被佔滿了,真是萬惡的帝國主義啊。
無可奈何,中國必須要自己重寫一張表來編碼咱們的漢字,於是直接生猛地將擴展的第八位(即擴展ascii碼)對應的拉丁文全部刪掉,規定一個小於127的字符的意義與原來相同,但兩個大於127的字符連在一起時,就表示一個漢字,前面的一個字節(稱爲高字節)從0xA1用到0xF7,後面一個字節(低字節)從0xA1到0xFE,這樣我們就可以組合出大約7000多個簡體漢字了;這種漢字方案叫做 “GB2312”。GB2312 是對 ASCII 的中文擴展。

3. GBK 編碼:

查看GBK編碼表/GBK字符集

定義:
GBK是包括中日韓字符的大字符集合,全國信息技術化技術委員會於1995年12月1日發佈的《漢字內碼擴展規範》。GBK 向下與 GB2312 完全兼容,向上支持 ISO
10646 國際標準,在前者向後者過渡過程中起到的承上啓下的作用。GBK 亦採用雙字節表示,總體編碼範圍爲 8140-FEFE之間,首字節在 81-FE 之間,尾字節在 40-FE 之間,剔除 XX7F 一條線。GBK 共收入 21886 個漢字和圖形符號
GBK 編碼區 分成三部分:

  • 漢字區,包括:
    GBK/2:OXBOA1-F7FE, 收錄 GB2312 漢字 6763 個,按原序排列;
    GBK/3:OX8140-AOFE,收錄 CJK 漢字 6080 個;
    GBK/4:OXAA40-FEAO,收錄 CJK 漢字和增補的漢字 8160 個。

  • 圖形符號區,包括:
    GBK/1:OXA1A1-A9FE,除 GB2312 的符號外,還增補了其它符號
    GBK/5:OXA840-A9AO,擴除非漢字區。

  • 用戶自定義區:
    即 GBK 區域中的空白區,用戶可以自己定義字符。

誕生:
儘管GB2312編碼可以讓計算機讀懂表示常用中文字符了,但是中國文化博大精深,漢字太多了,GB2312也不夠用,於是又規定:只要第一個字節是大於127就固定表示這是一個漢字的開始,不管後面跟的是不是擴展字符集裏的內容。這樣擴展之後的編碼方案被稱爲 GBK 標準,GBK 包括了 GB2312 的所有內容,同時GBK又增加了近20000個新的漢字(包括繁體字)和符號

4. gGB18030 編碼:

定義:
2000年的GB18030是取代GBK的正式國家標準。該標準收錄了27484個漢字,同時還收錄了藏文、蒙文、維吾爾文等主要的少數民族文字。GB18030 是最新的漢字編碼字符集國家標準, 向下兼容 GBK 和 GB2312 標準。

GB18030的編碼採用單字節、雙字節和4字節方案。其中單字節、雙字節和GBK是完全兼容的。4字節編碼的碼位就是收錄了CJK擴展A的6582個漢字。

GB18030編碼是一二四字節變長編碼。一字節部分從 0x0~0x7F 與 ASCII 編碼兼容。 二字節部分, 首字節從 0x81~0xFE,尾字節從 0x40~0x7E 以及 0x80~0xFE, 與 GBK 標準基本兼容。 四字節部分,第一字節從 0x81~0xFE, 第二字節從 0x30~0x39,第三和第四字節的範圍和前兩個字節分別相同。 四字節部分覆蓋了從 0x0080 開始, 除去二字節部分已經覆蓋的所有 Unicode碼位,也就是說, GB18030 編碼在碼位空間上做到了與 Unicode 標準一一對應,這一點與 UTF-8編碼類似。目前最新的 glibc 2.2.x 系列已經全面支持了 GB18030 Locale 和 GB18030 與 UCS-4之間的編碼轉換, 也就是說在系統層上 Linux 已經可以支持 GB18030 標準了。

5. Unicode 編碼:

定義:
Unicode(統一碼、萬國碼、單一碼)是一種在計算機上使用的字符編碼。Unicode 是爲了解決傳統的字符編碼方案的侷限而產生的,它爲每種語言中的每個字符設定了統一併且唯一的二進制編碼,規定雖有的字符和符號最少由 16 位來表示(2個字節),即:2 **16 = 65536。

誕生:
儘管有了ASCII編碼,GB2312編碼,GBK編碼,甚至別的國家也有自己的編碼字符集,但是各個國家的標準不同,並不兼容,對於互聯網而言,這嚴重阻礙了各個國家的交流。因此建立一個能統一世界各國語言的編碼迫不及待,Unicode便誕生了。

6. UTF-8 編碼:

定義:
UTF-8(8位元,Universal Character Set/Unicode Transformation Format)是針對Unicode的一種可變長度字符編碼。它可以用來表示Unicode標準中的任何字符,而且其編碼中的第一個字節仍與ASCII相容,使得原來處理ASCII字符的軟件無須或只進行少部份修改後,便可繼續使用。因此,它逐漸成爲電子郵件、網頁及其他存儲或傳送文字的應用中,優先採用的編碼。

誕生:
unicode都一統天下了,爲什麼還要有一個utf-8的編碼呢?

對於英文世界的人來講,比如要存儲字母’A‘,本來用00010001一個字節就可以了,而爲了世界和平改用Unicode得用兩個字節:00000000 00010001才行。

舉個例子:一個用ASCII編碼的大小爲20G的英文文件,如果改用Unicode編碼,文件大小會變成40G!浪費太嚴重。

基於此,美利堅的科學家們提出了天才的想法:UTF-8編碼
它可以使用1~4個字節表示一個符號,根據不同的符號而變化字節長度,當字符在ASCII碼的範圍時,就用一個字節表示,所以是兼容ASCII編碼的。

這樣顯著的好處是,雖然在我們內存中的數據都是unicode,但當數據要保存到磁盤或者用於網絡傳輸時,直接使用unicode就遠不如utf8省空間啦!這也是爲什麼utf-8是我們的推薦編碼方式。

7. BIG5 編碼:

定義:
BIG5是通行於臺灣、香港地區的一個繁體字編碼方案。雖然存在一些瑕疵,但廣泛應用於電腦行業,尤其是互聯網中,從而成爲一種事實上的行業標準。

BIG5 碼是雙字節編碼方案,其中第一個字節的值在 OXAO-OXFE 之間,第二個字節在 OX40-OX7E 和OXA1-OXFE 之間。

BIG5 收錄了13461個漢字和符號

三、對比總結

  • ASCII 收錄了所有的字母的大小寫,各種符號,拉丁文等共256種。用1個字節代表一個字符。

  • GB2312 收錄了簡化漢字及符號、字母、日文假名等共 7445 個圖形字符,其中漢字佔 6763 個。用2個字節表示一個字符,每個字節均採用七位編碼表示。

  • GBK 是中文的字符編碼,共收入 21886 個漢字和圖形符號。用2個字節代表一個字符。

  • GB18030 收錄了27484個漢字,同時還收錄了藏文、蒙文、維吾爾文等主要的少數民族文字。採用單字節、雙字節和四字節三種方式對字符編碼。 向下兼容 GBK 和 GB2312 。

  • Unicode 統一了世界各國語言的不同,統一用2個字節代表一個字符,速度快,但浪費空間。可以用在內存處理中,兼容utf-8,gbk,ascii。

  • UTF-8 爲了解決Unicode的浪費空間的缺點,規定1個英文字符用1個字節表示,1箇中文字符用3個字節表示,節省空間,但速度慢。在硬盤數據傳輸,網絡數據傳輸時,相比硬盤和網絡速度,體現不出來。

  • BIG5 是通行於臺灣、香港地區的一個繁體字編碼方案,收錄了13461個漢字和符號。用2個字節代表一個字符。

  • 從ASCII、GB2312、GBK 到GB18030、Unicode、UTF-8,這些編碼方法是向下兼容的,即同一個字符在這些方案中總是有相同的編碼,後面的標準支持更多的字符。

四、編碼轉換

請參考文章:GBK,Unicode,UTF-8編碼的相互轉換

最後:
推薦閱讀   編碼詳解(英文):https://diveintopython3.net/strings.html

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章