日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

【转】刨根究底字符编码之十——Unicode字符集的字符编码方式

發(fā)布時(shí)間:2023/12/10 编程问答 28 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【转】刨根究底字符编码之十——Unicode字符集的字符编码方式 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

一、字符編碼方式CEF的選擇

1.

由于Unicode字符集非常大(并且作為開(kāi)放字符集還在不斷擴(kuò)展之中),有些字符的編號(hào)(即碼點(diǎn)值)需要兩個(gè)或兩個(gè)以上字節(jié)來(lái)表示,而要對(duì)這樣的編號(hào)進(jìn)行編碼,也必須使用兩個(gè)或兩個(gè)以上字節(jié)。

比如,漢字“嚴(yán)”的Unicode編號(hào)以十六進(jìn)制數(shù)表示為4E25,轉(zhuǎn)換成二進(jìn)制數(shù)有15位(100 1110 0010 0101),對(duì)“嚴(yán)”這個(gè)字符的編號(hào)進(jìn)行編碼的話,至少需要2個(gè)字節(jié)。表示其他更大編號(hào)的字符,可能需要3個(gè)字節(jié)或者4個(gè)字節(jié),甚至更多。

2.

這帶來(lái)兩個(gè)問(wèn)題:

一是,如何才能區(qū)別Unicode字符和ASCII字符的編碼?計(jì)算機(jī)怎么知道三個(gè)字節(jié)表示的是一個(gè)字符,而不是分別表示三個(gè)字符呢?

二是,我們知道,英文字母只用一個(gè)字節(jié)來(lái)編碼就夠了,而如果Unicode統(tǒng)一硬性規(guī)定,每個(gè)字符都用兩個(gè)、三個(gè)或四個(gè)字節(jié)來(lái)編碼,那么每個(gè)英文字母編碼的前面都必然有一個(gè)、兩個(gè)到三個(gè)字節(jié)全是0,這對(duì)于存儲(chǔ)和傳輸來(lái)說(shuō)是極大的浪費(fèi)。

這就涉及到了字符編碼方式CEF的選擇問(wèn)題。Unicode字符的編碼方式目前最常用的是這三種:UTF-8、UTF-16、UTF-32。在具體介紹這些編碼方式之前,需要再次深入了解兩個(gè)概念——碼點(diǎn)(Code Point)與碼元(Code Unit)。

?

二、碼點(diǎn)

1.

一個(gè)字符集一般可以用一張或多張由多個(gè)行和多個(gè)列所構(gòu)成的二維表來(lái)表示。

二維表中行與列相交的點(diǎn),稱之為碼點(diǎn)(Code Point代碼點(diǎn)),也稱之為碼位(Code position代碼位);每個(gè)碼點(diǎn)分配一個(gè)唯一的編號(hào),稱之為碼點(diǎn)值或碼點(diǎn)編號(hào),除開(kāi)某些特殊區(qū)域(比如代理區(qū)、專用區(qū))的非字符碼點(diǎn)和保留碼點(diǎn),每個(gè)碼點(diǎn)唯一對(duì)應(yīng)于一個(gè)字符。

因此,除開(kāi)非字符碼點(diǎn)和保留碼點(diǎn),碼點(diǎn)值(即碼點(diǎn)編號(hào))通常來(lái)說(shuō)就是其所對(duì)應(yīng)的字符的編號(hào),所以碼點(diǎn)值有時(shí)也可以直接稱之為字符編號(hào),雖然不夠準(zhǔn)確,但更為直接。

2.

字符集中所有碼點(diǎn)數(shù)量的總和,稱之為編號(hào)空間(Code Space,又被稱之為代碼空間、編碼空間、碼點(diǎn)空間、碼空間)。

碼點(diǎn)值最初用兩個(gè)字節(jié)的十六進(jìn)制數(shù)字表示,比如字母A的Unicode碼點(diǎn)值為0041,常寫(xiě)作U+0041,這種形式稱為Unicode碼點(diǎn)名稱,不嚴(yán)格地來(lái)講,也可稱之Unicode字符名稱(因?yàn)榇嬖谥亲址a點(diǎn)和保留碼點(diǎn),并非每個(gè)碼點(diǎn)都分配了字符,所以這種稱呼不夠準(zhǔn)確,不過(guò)目前更為普遍)。

3.

后來(lái)隨著Unicode字符集的不斷增補(bǔ)擴(kuò)大(比如現(xiàn)在的Unicode字符集至少需要21位才能全部表示),碼點(diǎn)值也擴(kuò)展為用三個(gè)字節(jié)或以上的十六進(jìn)制數(shù)字表示。

例如,ASCII字符集用0~127這連續(xù)的128個(gè)數(shù)字編號(hào)分別表示128個(gè)字符。GBK字符集使用區(qū)位碼的方式為每個(gè)字符編號(hào),首先定義一個(gè)94×94的矩陣,行稱為“區(qū)”,列稱為“位”,然后將所有國(guó)標(biāo)漢字放入矩陣當(dāng)中,這樣每個(gè)漢字就可以用唯一的“區(qū)位”碼來(lái)標(biāo)識(shí)了。例如“中”字被放到54區(qū)第48位,因此其區(qū)位碼(字符編號(hào))就是5448。

而目前Unicode標(biāo)準(zhǔn)中,將字符按照一定的類別劃分到0~16這17個(gè)平面(Plane層面)中,每個(gè)平面中擁有2^16 = 65536個(gè)碼點(diǎn),因此,目前Unicode字符集所擁有的碼點(diǎn)總數(shù),也就是Unicode的編號(hào)空間為17*65536=1114112。

注意,網(wǎng)絡(luò)上的很多文章中,代碼點(diǎn)、碼點(diǎn)、碼點(diǎn)值、碼值、代碼位、碼位、字符碼、Unicode碼、字符編號(hào)、字符編碼、編碼方案、編碼方式、編碼格式等等概念經(jīng)常互相代替混用,讓人困惑。

(笨笨阿林原創(chuàng)文章,轉(zhuǎn)載請(qǐng)注明出處)

?

三、碼元

1.

在計(jì)算機(jī)存儲(chǔ)和網(wǎng)絡(luò)傳輸時(shí),碼點(diǎn)值(即字符編號(hào))被映射到一個(gè)或多個(gè)碼元(Code Unit代碼單元、編碼單元)

碼元可理解為字符編碼方式CEF(Character Encoding Form)對(duì)碼點(diǎn)值進(jìn)行編碼處理時(shí)作為一個(gè)整體來(lái)看待的最小基本單元(或稱為最小基本單位)

2.

為什么非要引入“碼元”這個(gè)概念?或者說(shuō),為什么非要強(qiáng)調(diào)“碼元”這個(gè)概念?

碼元某種程度上可認(rèn)為對(duì)應(yīng)于高級(jí)語(yǔ)言中的基本數(shù)據(jù)類型。而高級(jí)語(yǔ)言層面的基本數(shù)據(jù)類型,若要更深入一步地來(lái)講,實(shí)質(zhì)上對(duì)應(yīng)于機(jī)器硬件層面(如匯編語(yǔ)言層面)的數(shù)據(jù)類型byte字節(jié)、word字、dword雙字等在硬件中的表達(dá)與處理機(jī)制。

之所以要強(qiáng)調(diào)“碼元”的概念,是因?yàn)樽址幋a作為一串?dāng)?shù)字序列,最終還是得通過(guò)機(jī)器硬件層面的數(shù)據(jù)類型來(lái)表示。

而碼元的實(shí)質(zhì),就是機(jī)器硬件層面的數(shù)據(jù)類型;不同的碼元,代表著不同位數(shù)的數(shù)據(jù)類型。當(dāng)字符編碼方案設(shè)計(jì)人員基于某種考慮(如時(shí)間復(fù)雜度、空間復(fù)雜度等)為某種字符編碼方式CEF選擇了某種碼元時(shí),其實(shí)質(zhì)就是選擇了某個(gè)位數(shù)的數(shù)據(jù)類型。

數(shù)據(jù)類型,在機(jī)器硬件層面上來(lái)看,只有作為一個(gè)整體來(lái)處理的二進(jìn)制數(shù)字位數(shù)上的不同(如byte字節(jié)、word字、dword雙字等匯編語(yǔ)言的數(shù)據(jù)類型,都是二進(jìn)制數(shù)字值,只是位數(shù)不同而已),而并沒(méi)有高級(jí)語(yǔ)言層面上的數(shù)值、布爾、字符等語(yǔ)義的不同,畢竟本質(zhì)上來(lái)講計(jì)算機(jī)只“認(rèn)識(shí)”由0和1組成的數(shù)字。

正因?yàn)槿绱?#xff0c;字符編碼方案設(shè)計(jì)人員在設(shè)計(jì)字符編碼方式CEF時(shí),必然要選擇一種機(jī)器硬件層面上某個(gè)位數(shù)的數(shù)據(jù)類型(如byte字節(jié)、word字、dword雙字等)來(lái)表示,不是選擇這個(gè)位數(shù)的數(shù)據(jù)類型,就是選擇那個(gè)位數(shù)的數(shù)據(jù)類型。當(dāng)然這種選擇會(huì)基于各種考慮,比如時(shí)間復(fù)雜度、空間復(fù)雜度等,不過(guò)一旦選擇了某種數(shù)據(jù)類型,其所選擇的數(shù)據(jù)類型位數(shù)上的不同,同時(shí)也就體現(xiàn)為了碼元位數(shù)上的不同。

所以,不同位數(shù)的碼元,實(shí)質(zhì)上是機(jī)器硬件層面上不同位數(shù)的數(shù)據(jù)類型。(而機(jī)器硬件層面上為什么要設(shè)計(jì)不同位數(shù)的多種數(shù)據(jù)類型出來(lái),這是另一個(gè)話題了,有興趣可參看有關(guān)硬件方面的專著。)

3.

由于數(shù)據(jù)類型有單字節(jié)與多字節(jié)之分,所以碼元也有單字節(jié)與多字節(jié)之分;而多字節(jié)數(shù)據(jù)類型由于歷史的原因,存在著字節(jié)序的大端序(Big-Endian)與小端序(Little-Endian)之分,因此多字節(jié)碼元也存在著大端序與小端序之分(具體詳見(jiàn)前文中有關(guān)字節(jié)序的解釋;注意,單字節(jié)數(shù)據(jù)類型是沒(méi)有字節(jié)序的問(wèn)題的,所以單字節(jié)碼元也就沒(méi)有字節(jié)序問(wèn)題)。

這就是之所以要強(qiáng)調(diào)“碼元”這個(gè)概念的關(guān)鍵原因。

4.

對(duì)字符編號(hào)(即字符碼點(diǎn)值)進(jìn)行編碼的具體實(shí)現(xiàn)方式——字符編碼方式CEF,就是由一個(gè)或多個(gè)碼元這樣的最小基本單元構(gòu)成的。

最常用的碼元是8位(即1字節(jié))的單字節(jié)碼元,另外還有16位(即2字節(jié))和32位(即4字節(jié))兩種多字節(jié)碼元,分別相當(dāng)于匯編語(yǔ)言中的byte字節(jié)、word字、dword雙字,以及C++中的無(wú)符號(hào)整型BYTE、WORD、DWORD。

(注:?在VC++6.0中,這三種數(shù)據(jù)類型的定義分別為:

   typedef unsigned char BYTE; // 1個(gè)字節(jié)

   typedef unsigned short WORD; // 2個(gè)字節(jié)

   typedef unsigned long DWORD; // 4個(gè)字節(jié))

(笨笨阿林原創(chuàng)文章,轉(zhuǎn)載請(qǐng)注明出處)

5.

于是,三種碼元對(duì)應(yīng)就有了Unicode字符編號(hào)的三種UTF編碼方式(即Unicode碼轉(zhuǎn)換格式Unicode Transformation Format,或稱通用字符集轉(zhuǎn)換格式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。

或者反過(guò)來(lái)說(shuō),Unicode字符編號(hào)的三種UTF編碼方式(UTF-8、UTF-16、UTF-32)分別采用了不同的碼元(單字節(jié)、雙字節(jié)、四字節(jié))來(lái)編碼。

例如,“漢字”這兩個(gè)中文字符的Unicode字符編號(hào)是0x6C49和0x5B57,其三種UTF編碼在VC++6.0中可按如下定義進(jìn)行“模擬”:

6.

注意,這里之所以說(shuō)是“模擬”,其中的一個(gè)重要原因,如前文所述,從本質(zhì)上來(lái)講機(jī)器硬件層面上的所有數(shù)據(jù)類型,只存在著被視作一個(gè)整體來(lái)處理的比特序列(即二進(jìn)制序列)的位數(shù)不同之分,不存在著高級(jí)語(yǔ)言層面上數(shù)據(jù)類型的數(shù)值、字符串、布爾值等的語(yǔ)義不同之分。

因此,機(jī)器硬件層面上的數(shù)據(jù)類型與高級(jí)語(yǔ)言層面上的數(shù)據(jù)類型,嚴(yán)格來(lái)講,在含義上還是有著很大不同的。當(dāng)然,高級(jí)語(yǔ)言層面上的數(shù)據(jù)類型最終還是會(huì)被轉(zhuǎn)化為機(jī)器硬件層面上的數(shù)據(jù)類型,畢竟計(jì)算機(jī)只“認(rèn)識(shí)”由0和1所組成的比特流。(可同時(shí)參見(jiàn)前文中有關(guān)字節(jié)序的解釋)

7.

這里用BYTE、WORD、DWORD分別表示無(wú)符號(hào)8位整數(shù)、無(wú)符號(hào)16位整數(shù)和無(wú)符號(hào)32位整數(shù);因而UTF-8、UTF-16、UTF-32可認(rèn)為分別以BYTE、WORD、DWORD作為碼元。

“漢字”這兩個(gè)中文字符的UTF-8編碼需要六個(gè)BYTE(共6個(gè)單字節(jié)碼元),大小是6個(gè)字節(jié);UTF-16編碼需要兩個(gè)WORD(共2個(gè)雙字節(jié)碼元),大小是4個(gè)字節(jié);UTF-32編碼需要兩個(gè)DWORD(共2個(gè)四字節(jié)碼元),大小是8個(gè)字節(jié)。

由于多字節(jié)數(shù)據(jù)類型的數(shù)據(jù)在計(jì)算機(jī)存取時(shí)存在一個(gè)字節(jié)序的問(wèn)題,因此,UTF-16、UTF-32這兩種編碼方式所編碼出來(lái)的邏輯意義上的多字節(jié)碼元序列,在映射為物理意義上的字節(jié)序列時(shí),字節(jié)序列的字節(jié)序因系統(tǒng)平臺(tái)的不同而不同。

前面已經(jīng)多次強(qiáng)調(diào)過(guò)了,這里再次特別強(qiáng)調(diào)一下:由單字節(jié)數(shù)據(jù)類型所組成的多字節(jié)數(shù)據(jù)是不存在字節(jié)序的問(wèn)題的。因此,采用單字節(jié)碼元進(jìn)行編碼的UTF-8編碼,雖然ASCII字符為單字節(jié)編碼,而非ASCII字符卻是多字節(jié)編碼的,但卻并不存在字節(jié)序問(wèn)題,這是跟同樣為多字節(jié)編碼、但卻采用多字節(jié)碼元的UTF-16、UTF-32編碼的不同之處。詳見(jiàn)下表所列。

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

(笨笨阿林原創(chuàng)文章,轉(zhuǎn)載請(qǐng)注明出處)

?

【預(yù)告:下一篇將重點(diǎn)講解UTF-8編碼方式與字節(jié)序標(biāo)記(BOM),敬請(qǐng)關(guān)注!

?

總結(jié)

以上是生活随笔為你收集整理的【转】刨根究底字符编码之十——Unicode字符集的字符编码方式的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。