ASCII和Unicode編碼詳解

2021-06-26 13:01:31 字數 3463 閱讀 8872

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

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

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

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

在標準的ascii中,最高位(b7)用作奇偶校驗位。奇校驗規定:正確的**乙個位元組中1的個數必須是奇數,若非奇數,則在最高位b7添1;偶校驗道理相似。

由於標準ascii字符集字元數目有限,無法滿足需求,國際標準組織在相容的前提下,將ascii字符集擴充為8位**的統一方法,後面補充的這128個字元編碼就稱為擴充套件ascii碼。

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是乙個字符集,收錄的字元和編碼是唯一對應的,它只規定了如何編碼,並沒有規定如何儲存、傳輸這個編碼。所以我們說unicode只完成了一半的工作,還需要定義一種方法來確定碼位在記憶體和硬碟中如何表示,unicode標準為此定義了幾種對映,稱為unicode轉換格式,簡稱utf。

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

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

在bmp中,從u+d800到u+dfff之間的碼位區段是永久保留不對映的字元,utf-16就是利用保留下來的這個區段碼位來對映輔助平面的字元的碼位。

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,首先我們我三位元組的框架搭好: 

1110***x 10****** 10******

b)       查到朕的十六進製制unicode編碼是\u6715,轉換為二進位制**是

01100111 00010101

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

0110

0111 00

010101

1110***x 10****** 10******

11100110 10011100 10010101

d)       將上述的二進位制字串轉換為16進製制就是

\xe6\x9c\x95

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

gbk是gb2312的擴充套件,除了相容gb2312外,還收錄了中文繁體、日語中的一些字元。

六.    混淆點

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

unicode\gbk\gb2312是編碼字符集

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

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使用者最常見的乙個異常,其根本原因就在於此。

關於ASCII和Unicode字集

void cdrawview onlbuttondown uint nflags,cpoint point 錯誤 error c2664 cwnd messageboxw 不能將引數 1 從 const char 75 轉換為 lpctstr messagebox t don t create do...

Unicode是什麼編碼,與ASCII的關係

今天在看python的轉義字元的時候,在字串中寫 u x的時候出現錯誤 syntaxerror unicodeerror,於是搜了一下unicode。1 utf 32 將字元的unicode編號直接轉換成二進位制儲存。使用4個位元組,即32位。2 utf 16 utf 16使用變長位元組表示,使用2...

多字元編碼 和 Unicode編碼

四字符集和字元編碼說明 五 其他 c 基本資料型別中表示字元有兩種 char wchar t char 叫多位元組字元,乙個char佔乙個位元組,之所以叫多位元組字元是因為它表示乙個字時可能是乙個位元組也可能是多個位元組。乙個英文本元 如 s 用乙個char 乙個位元組 表示,乙個中文漢字 如 中 ...