ASCII和Unicode編碼詳解

本文參考大量維基百科和網絡大牛的文章,並結合實際例子,試圖幫助大家理清計算機的編碼問題,從而更加高效的編寫程序。

一.    知識補充

1.1  位

我們常說的位是指比特位,即bit,每一個bit位存儲一個0或者1。所以,在計算機(二進制數系統)中,一個位(bit)就是指一個0或者1。我們說計算機的CPU一次能處理的最大位數就是指這個位。

1.2  字節

字節(Byte)是指一小組相鄰的二進制數碼,每8個位組成一個字節,即1Byte = 8bit。我們通俗的說,8個0或者1組成一個字節。字節是計算機基本的信息存儲和處理單位。

二.    ASCII

ASCII是由美國製定的標準單字節字符編碼方案,主要用於顯示現代英語。標準ASCII碼使用7位二進制數來表示所有的大寫和小寫字母、數字0~9、標點符號和特殊控制字符,共計128個字符,具體可以參照ASCII對照表查看。

在標準的ASCII中,最高位(b7)用作奇偶校驗位。奇校驗規定:正確的代碼一個字節中1的個數必須是奇數,若非奇數,則在最高位b7添1;偶校驗道理相似。

由於標準ASCII字符集字符數目有限,無法滿足需求,國際標準組織在兼容的前提下,將ASCII字符集擴充爲8位代碼的統一方法,後面補充的這128個字符編碼就稱爲擴展ASCII碼。

三.    Unicode

Unicode和UCS的詳細區別請google。

前面說到8位ASCII遠遠不能滿足所有字符的編碼需求,怎麼辦?增加二進制表示的位數。最初版本的unicode字符編碼採用16位,這樣就能表示65536個碼位,此版本也稱UCS2。這對於表示世界上大多數的語言、字符已經是充裕的了。

但是爲什麼說只是充裕的?因爲這些組織在制定這些字符集的時候就想了,如果有一天,外星人來到地球,並帶來了新的語言或符號,或者我們人類進化,某個種族突然創造出一種新的語言怎麼辦?好吧,在16位的基礎上再加16位,現在32位,夠了吧?這就是UCS-4版本,UCS-4是一個更大的32位字符集,最高位恆爲0,可以表示2^31個字符,這樣足夠了,但是實際並非如此。

在UCS4中,所有的編碼空間被分爲17個平面,每個平面包含2^16個碼位。第一個平面稱爲基本多語言平面(BMP),也稱第0平面,與我們現在實際中用的UCS-2編碼相同,BMP使用16位的編碼空間,碼位從U+0000到U+FFFF,包含了我們常用的字符。

到這裏,我們已經把全世界有的沒有的語言、符號都賦予了一個唯一的二進制碼位。似乎是沒問題了,但是美國不同意了,爲什麼?因爲我們前面說美國製定的ASCII編碼,只用一個字節就能表示他們用到的所有大小寫字母、字符等,爲什麼要換成佔用兩個字節unicode?而且高字節的八個位都是0,這樣對存儲空間和傳輸空間都是浪費。爲了解決這個這個問題,UCS字符U+0000到U+007F被編碼爲字節0X00到0X7F,只佔用1個字節,這樣unicode便與ASCII兼容了。

下面我們舉例演示unicode編碼:

A  à  \u41

朕 à   \u6715

字母A的unicode編碼是\u41,1個字節,轉換二進制是 0100 0001,和A的ASCII碼一致。

中文“朕”的unicode編碼是\u6715,2個字節,轉換二進制是

01100111 0001 0101,

unicode的工作是制定了類似“朕”與0110 0111 0001 0101之間唯一的映射。

四.    Unicode實現方式UTF

Unicode是一個字符集,收錄的字符和編碼是唯一對應的,它只規定了如何編碼,並沒有規定如何保存、傳輸這個編碼。所以我們說unicode只完成了一半的工作,還需要定義一種方法來確定碼位在內存和硬盤中如何表示,unicode標準爲此定義了幾種映射,稱爲unicode轉換格式,簡稱UTF。

1.      UTF-32

我們首先介紹UTF-32,UTF-32是最清楚的,但是使用最少的一個。爲何?每一個碼位使用整32位,因此每一個UTF-32值都可以直接表示對應的碼位。然而,UTF-32幾乎從來沒在實際中使用過,因爲每個字符佔用4個字節,這樣就太浪費空間了。

2.      UTF-16

前面我們說到Unicode編碼空間被劃分爲17個平面,每個平面包括65536個碼位。第一個平面稱爲基本多語言平面,簡稱BMP,其它平面稱爲輔助平面。

在BMP中,從U+D800到U+DFFF之間的碼位區段是永久保留不映射的字符,UTF-16就是利用保留下來的這個區段碼位來映射輔助平面的字符的碼位。

3.      UTF-8

UTF-8使用1-6個字節爲每個字符編碼:

一個字節編碼128個ASCII字符(U+0000---U+007F);

二個字節編碼拉丁文等附帶符號的其它字符(U+0080---U+07FF);

三個字節編碼BMP中的其它字符,包括中文;

四~六個字節編碼unicode輔助平面的字符。

UTF-8的編碼規則:

1)單字節符號,最高位爲0,後面7位爲這個符號的unicode碼,因此一個字符表示的UTF-8編碼與對應的ASCII碼是相同的;

2)N(N>1)字節符號,最高字節的前N位全爲1、第N+1位爲0,後面字節的前兩位爲10,所有字節剩餘的位,由符號的unicode碼補充。

下面舉例演示UTF-8的編碼規則:

a)       中文“朕”是BMP中的字符,編碼爲UTF-8使用3 個字符,根據UTF-8的編碼規則2,首先我們我三字節的框架搭好: 

1110xxxx 10xxxxxx 10xxxxxx

b)       查到朕的十六進制unicode編碼是\u6715,轉換爲二進制代碼是

01100111 00010101

c)       將這串二進制代碼填充空餘處(如顏色示意):

01100111 00010101

1110xxxx 10xxxxxx 10xxxxxx

11100110 10011100 10010101

d)       將上述的二進制字符串轉換爲16進制就是

\xe6\x9c\x95

五.     中文編碼

1.      GB2312字符集

GB2312是中國規定的漢字編碼,也可以說是簡體中文的字符集編碼,共收錄6763個漢字和682個字符,每個漢字及符號以兩個字節來表示

2.      GBK

GBK是GB2312的擴展,除了兼容GB2312外,還收錄了中文繁體、日語中的一些字符。

六.    混淆點

1.      UTF不是一種編碼,只是unicode編碼的一種儲存和傳送格式

Unicode\GBK\GB2312是編碼字符集

2.      UTF-8碼完全針對unicode,如果GBK要轉爲UTF-8,必須先轉爲unicode碼,然後才能轉爲UTF-8,反之一樣。

 

七.    Python的編碼問題

1.      python 2.x編碼問題根源

Python2.x版本編寫的程序默認採用ASCII編碼,這個通過sys模塊便能直接看到看到。

       Import sys

       Print sys.getdefaultencodeing()

根據上面我們對ASCII的編碼格式分析,ASCII只能識別包含大小寫英文字母、特殊字符個標點符號在內的128個字符,那麼問題就來了,如果在我們的代碼中使用了某些個超出ASCII編碼範圍的字符,比如中文,python解釋器就不能識別這個特殊的字符,所以會報出瞭如下的錯誤:

UnicodeDecodeError:'ascii' codec can't decode byte 0x?? in position x: ordinal not in range(128)

初期python使用者最常見的一個異常,其根本原因就在於此。

 

 

發佈了31 篇原創文章 · 獲贊 3 · 訪問量 4萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章