刨根究底字符編碼之十——Unicode字符集的編碼方式以及碼點、碼元

Unicode字符集的編碼方式以及碼點、碼元

 

1、字符編碼方式CEF的選擇網絡

1.編碼

因爲Unicode字符集很是大,有些字符的編號(碼點值)須要兩個或兩個以上字節來表示,而要對這樣的編號進行編碼,也必須使用兩個或兩個以上字節。spa

好比,漢字「嚴」的Unicode碼(Unicode碼點值、Unicode編號)是十六進制數4E25,轉換成二進制數有15位(100 1110 0010 0101),對「嚴」這個字符的編號進行編碼的話,至少須要2個字節。表示其餘更大編號的字符,可能須要3個字節或者4個字節,甚至更多。代理

2.code

這帶來兩個問題:orm

一是,如何才能區別Unicode字符和ASCII字符的編碼?計算機怎麼知道三個字節表示的是一個字符,而不是分別表示三個字符呢?blog

二是,咱們知道,英文字母只用一個字節來編碼就夠了,而若是Unicode統一硬性規定,每一個字符都用兩個、三個或四個字節來編碼,那麼每一個英文字母編碼的前面都必然有一個、兩個到三個字節全是0,這對於存儲和傳輸來講是極大的浪費。字符串

這就涉及到了字符編碼方式CEF的選擇問題。Unicode字符的編碼方式通常有三種:UFF-八、UTF-1六、UTF-32。在具體介紹這些編碼方式以前,須要再次深刻了解兩個概念——碼點(Code Point)與碼元(Code Unit)。it

 

2、碼點io

1.

一個字符集通常能夠用一張或多張由多個行和多個列所構成的二維表來表示。

二維表中行與列相交的點,稱之爲碼點(Code Point代碼點),也稱之爲碼位(Code position代碼位);每一個碼點分配一個惟一的編號,稱之爲碼點值或碼點編號,除開某些特殊區域(好比代理區、專用區)的非字符碼點和保留碼點,每一個碼點惟一對應於一個字符。

所以,除開非字符碼點和保留碼點,碼點值(即碼點編號)一般來講就是其所對應的字符的編號,因此碼點值有時也能夠直接稱之爲字符編號,雖然不夠準確,但更爲直接。

2.

字符集中全部碼點數量的總和,稱之爲編號空間(Code Space,又被稱之爲代碼空間、編碼空間、碼點空間、碼空間)。

碼點值最初用兩個字節的十六進制數字表示,好比字母A的Unicode碼點值爲0041,常寫做U+0041,這種形式稱爲Unicode碼點名稱,不嚴格地來說,也可稱之Unicode字符名稱(由於存在着非字符碼點和保留碼點,並不是每一個碼點都分配了字符,因此這種稱呼不夠準確,不過目前更爲廣泛)。

3.

後來隨着Unicode字符集的不斷增補擴大(好比如今的Unicode字符集至少須要21位才能所有表示),碼點值也擴展爲用三個字節或以上的十六進制數字表示。

例如,ASCII字符集用0~127這連續的128個數字編號分別表示128個字符。GBK字符集使用區位碼的方式爲每一個字符編號,首先定義一個94×94的矩陣,行稱爲「區」,列稱爲「位」,而後將全部國標漢字放入矩陣當中,這樣每一個漢字就能夠用惟一的「區位」碼來標識了。例如「中」字被放到54區第48位,所以其區位碼(字符編號)就是5448。

而目前Unicode標準中,將字符按照必定的類別劃分到0~16這17個平面(Plane層面)中,每一個平面中擁有2^16 = 65536個碼點,所以,目前Unicode字符集所擁有的碼點總數,也就是Unicode的編號空間爲17*65536=1114112。

 

注意,網絡上的不少文章中,代碼點、碼點、碼點值、碼值、代碼位、碼位、字符碼、Unicode碼、字符編號、字符編碼、編碼方案、編碼方式、編碼格式等等常常互相代替混用。

(笨笨阿林原創文章,轉載請註明出處)

 

3、碼元

1.

在計算機存儲和網絡傳輸時,碼點值(即字符編號)被映射到一個或多個碼元(Code Unit代碼單元、編碼單元)

碼元可理解爲字符編碼方式CEF(Character Encoding Form)對碼點值進行編碼處理時做爲一個總體來看待的最小基本單元(基本單位)

2.

爲何非要引入「碼元」這個概念?或者說,爲何非要強調「碼元」這個概念?

碼元某種程度上可認爲對應於高級語言中的基本數據類型。而高級語言層面的基本數據類型,若要更深刻一步地來說,實質上對應於機器硬件層面(彙編語言)的數據類型byte字節、word字、dword雙字等在硬件中的表達與處理機制。

之因此要強調「碼元」的概念,是由於字符編碼做爲一串數字序列,最終仍是得經過機器硬件層面的數據類型來表示。

而碼元的實質,就是機器硬件層面(彙編語言)的數據類型;不一樣的碼元,表明着不一樣位數的數據類型。

3.

數據類型有單字節與多字節之分,因此碼元也有單字節與多字節之分;多字節數據類型因爲歷史的緣由,存在着字節序的所謂大端序(Big-Endian)與小端序(Little-Endian)之分,所以多字節碼元也存在着大端序與小端序之分(具體詳見前文中有關字節序的解釋;注意,單字節數據類型則沒有字節序的問題,因此單字節碼元也就沒有字節序問題)。

這就是之因此要強調「碼元」這個概念的關鍵緣由。

4.

碼點值(即字符編號)的具體實現方式——字符編碼方式CEF,就是由一個或多個碼元這樣的最小基本單元構成的。

最經常使用的碼元是8位(1字節)的單字節碼元,另外還有16位(2字節)和32位(4字節)兩種多字節碼元,分別至關於C++中的無符號整型BYTE、WORD、DWORD(在VC++6.0中,這三種數據類型的定義分別爲:

typedef unsigned char BYTE;,1個字節;

typedef unsigned short WORD;,2個字節;

typedef unsigned long DWORD;,4個字節)。

(笨笨阿林原創文章,轉載請註明出處)

5.

因而,三種碼元對應就有了Unicode字符編號(碼點值)的三種UTF編碼方式(即Unicode碼轉換格式Unicode Transformation Format,或稱通用字符集轉換格式UCS Transformation Format):

UTF-8(8-bit Unicode/UCS Transformation Format),

UTF-16(16-bit Unicode/UCS Transformation Format),

UTF-32(32-bit Unicode/UCS Transformation Format);

或者反過來講,Unicode字符編號(碼點值)的三種UTF編碼方式(UTF-八、UTF-1六、UTF-32)分別採用了不一樣的碼元(BYTE、WORD、DWORD)來編碼。

例如,「漢字」這兩個中文字符的Unicode碼點值(Unicode字符編號)是0x6C49和0x5B57,其三種UTF編碼在VC++6.0中可按以下定義進行「模擬」:

 6.

注意,這裏之因此說是「模擬」,由於從本質上來說,在機器硬件層面上的全部數據類型,只存在着被視做一個總體來處理的比特序列(比特流)的位數不一樣之分,不存在着高級語言層面上數據類型的數值、字符串、布爾值等的語義不一樣之分。

所以,機器硬件層面上的數據類型與高級語言層面上的數據類型,嚴格來說,在本質含義上仍是有着很大不一樣的。固然,高級語言層面上的數據類型最終仍是會被轉化爲機器硬件層面上的數據類型,畢竟計算機只「認識」由0和1所組成的比特流。具體詳見前文中有關字節序的解釋。

7.

這裏用BYTE、WORD、DWORD分別表示無符號8位整數、無符號16位整數和無符號32位整數;於是UTF-八、UTF-1六、UTF-32可認爲分別以BYTE、WORD、DWORD做爲碼元。

「漢字」這兩個中文字符的UTF-8編碼須要六個BYTE(共6個單字節碼元),大小是6個字節;UTF-16編碼須要兩個WORD(共2個雙字節碼元),大小是4個字節;UTF-32編碼須要兩個DWORD(共2個四字節碼元),大小是8個字節。

因爲多字節數據類型的數據在計算機存取時存在一個字節序的問題,所以,UTF-1六、UTF-32這兩種編碼方式所編碼出來的邏輯意義上的多字節碼元序列,在映射爲物理意義上的字節序列時,字節序列的字節序因系統平臺的不一樣而不一樣。

前面已經屢次強調過了,這裏再次特別強調一下:由單字節數據類型所組成的多字節數據是不存在字節序的問題的。所以,採用單字節碼元進行編碼的UTF-8編碼,雖然ASCII字符爲單字節編碼,但非ASCII字符是多字節編碼的,但卻不存在字節序問題,這是跟一樣爲多字節編碼、但採用多字節碼元的UTF-1六、UTF-32不一樣之處。詳見下表所列:

 Unicode字符集三大編碼方式(UTF-八、UTF-1六、UTF-32)比較一覽表 


(笨笨阿林原創文章,轉載請註明出處)

 

【預告:下一篇將重點講解UTF-8編碼方式與字節序標記(BOM),敬請關注!

相關文章
相關標籤/搜索