久久国产成人av_抖音国产毛片_a片网站免费观看_A片无码播放手机在线观看,色五月在线观看,亚洲精品m在线观看,女人自慰的免费网址,悠悠在线观看精品视频,一级日本片免费的,亚洲精品久,国产精品成人久久久久久久

分享

Unicode編碼及其實(shí)現(xiàn):UTF-16,、UTF-8,,and more

 lhzstudio 2012-05-07

田海立@CSDN

2012-04-25


本文主要討論Unicode的編碼及其各種實(shí)現(xiàn),著重討論UTF-16,,UTF-8的實(shí)現(xiàn)規(guī)則,,以及Big-endian和Little-Endian的存儲(chǔ)順序。


一,、Unicode編碼


        Unicode出現(xiàn)之前已經(jīng)有各種編碼標(biāo)準(zhǔn):ANSI,、ISO8859-1、GB2312,、GBK以及BIG-5等,。Unicode試圖統(tǒng)一各種編碼,在Unicode演進(jìn)過程中,也有自身不斷修復(fù)的過程:剛開始的時(shí)候用16位表達(dá)65535個(gè)字符,,認(rèn)為已經(jīng)足夠收集所有的字符,;后來隨著大量中文、韓文和日文等表意文字的加入,,已經(jīng)超出了65535個(gè)字符,,16位已經(jīng)不能描述所有的字符集了。

        在Unicode字符集中的某個(gè)字符對(duì)應(yīng)的代碼值,,稱作代碼點(diǎn)(Code Point),,用16進(jìn)制書寫,,并加上U+前綴,。比如,‘田’的代碼點(diǎn)是U+7530,;‘A’的代碼點(diǎn)是U+0041,。

        Unicode定義的字符集已經(jīng)超過16位所能表達(dá)的范圍,把所有這些CodePoint分成17個(gè)代碼平面(Code Plane)

  • U+0000 ~ U+FFFF劃入基本多語言平面(Basic MultilingualPlane,,簡(jiǎn)記為BMP),;
  • 其余劃入16個(gè)輔助平面(Supplementary Plane),代碼點(diǎn)范圍U+10000 ~ U+10FFFF,。

        雖然這樣劃分,,但并不是每個(gè)Plane中的Code point都對(duì)應(yīng)有字符,這里面有保留的,,還有特殊用途的,。


二、Unicode編碼的實(shí)現(xiàn)


        Unicode的實(shí)現(xiàn)方式不同于編碼方式,。一個(gè)字符的Unicode編碼是確定的,,但是在實(shí)際存儲(chǔ)和傳輸過程中,由于不同系統(tǒng)平臺(tái)的設(shè)計(jì)不一定一致,,以及出于節(jié)省空間的目的,,對(duì)Unicode編碼的實(shí)現(xiàn)方式有所不同。Unicode的實(shí)現(xiàn)方式稱為Unicode轉(zhuǎn)換格式(Unicode Transformation Format,,簡(jiǎn)稱為UTF),。

        對(duì)Unicode編碼的主要有UTF-16BE、UTF-16LE,、UTF-8,、UTF-7以及UTF-32等實(shí)現(xiàn)方式,目前常用的實(shí)現(xiàn)方式是UTF-16LE,、UTF-16BE和UTF-8,。


2.1 UTF-16

        UTF-16是用16bit編碼來表達(dá)Unicode,這樣表達(dá)范圍是216(即65536),也就是UTF-16的代碼單元(Code Unit)為16bits,。如果表達(dá)BMP內(nèi)的字符,,用一個(gè)UTF-16的Code Unit就可表達(dá),對(duì)于輔助平面內(nèi)的字符,,UTF-16有巧妙的設(shè)計(jì),。

        落在BMP內(nèi),從U+D800U+DFFF之間的Code Point區(qū)段是永久保留不映射到字符,, UTF-16利用這保留下來的0xD800-0xDFFF區(qū)段的CodePoint來對(duì)輔助平面內(nèi)的字符的Code Point進(jìn)行編碼,。


對(duì)U+0000.. U+D7FF以及U+E000.. U+FFFF的編碼

        UTF-16與UCS-2對(duì)這個(gè)范圍內(nèi)的CodePoint進(jìn)行編碼,采用單個(gè)16bit長(zhǎng)的CodeUnit,,數(shù)值等價(jià)于對(duì)應(yīng)的Code Point,。BMP中的這些Code Point是僅有的可以被UCS-2表示的Code Point。

對(duì)U+10000.. U+10FFFF的編碼

        輔助平面(Supplementary Planes)中的CodePoint,,在UTF-16中被編碼為一對(duì)16bit長(zhǎng)的Code Unit(即32bit,,4Bytes),稱作代理對(duì)(surrogate pair),。


 具體方法是:

UTF-16解碼

hi \ lo

DC00

DC01

   …   

DFFF

D800

10000

10001

103FF

D801

10400

10401

107FF

  

DBFF

10FC00

10FC01

10FFFF

  1. Code Point減去0x10000,, 得到的值是長(zhǎng)度為20bit(0..0xFFFFF);
  2. 步驟1得到數(shù)值的高位的10比特的值(值范圍為0..0x3FF)被加上0xD800得到第一個(gè)Code Unit或稱作高位代理(high surrogate)或前導(dǎo)代理(lead surrogate),。取值范圍是0xD800..0xDBFF,。
  3. 步驟1得到數(shù)值的低位的10比特的值(值范圍為0..0x3FF)被加上0xDC00得到第二個(gè)Code Unit或稱作低位代理(low surrogate)或后尾代理(trail surrogate)。取值范圍是0xDC00..0xDFFF,。

        這樣,,這個(gè)范圍內(nèi)的字符就被編碼成了一個(gè)代理對(duì)[lead surrogate,trail surrogate]:兩個(gè)16bits的Code Unit,取值范圍分別是0xD800..0xDBFF和0xDC00..0xDFFF,。而BMP中得到的Code Unit的范圍是0x0000..0xFFFF(0xD800..0xDFFF是保留的,,不包含其中),所以這三個(gè)區(qū)段是相互不重疊的,,在解碼時(shí)很容易實(shí)現(xiàn),。

        UTF-16解碼[高位代理+低位代理]得到的Code Unit對(duì)與Code Point的對(duì)應(yīng)關(guān)系如上表所示。


        下面以對(duì)U+64321的UTF-16編碼為例,,看一下對(duì)于輔助平面內(nèi)的字符是如何編碼的:

V  = 0x64321

Vx = V - 0x10000

     = 0x54321

     = 01010100 0011 0010 0001

 

Vh = 01 0101 0000 // Vx 的高位部份的 10 bits

Vl  = 11 0010 0001 // Vx 的低位部份的 10 bits

w1 = 0xD800           // 結(jié)果的前16位元初始值

w2 = 0xDC00          // 結(jié)果的后16位元初始值

 

w1 = w1 | Vh

   = 1101 1000 0000 0000

     |             01 0101 0000

   = 1101 1001 0101 0000

   = 0xD950

 

w2 = w2 | Vl

   = 1101 1100 0000 0000

    |              11 0010 0001

   = 1101 1111 0010 0001

   = 0xDF21


        所以,,這個(gè)字 U+64321 最終的 UTF-16 編碼是:

0xD950 0xDF21


        UTF-16的Code Unit是16bits,兩個(gè)字節(jié),。存儲(chǔ)一個(gè)Code Unit的時(shí)候,,還有存取的先后順序問題,也就是Endian問題,,這在后面章節(jié)講述,。


2.2 UTF-8

        UTF-8(8-bit Unicode Transformation Format)是一種針對(duì)Unicode的可變長(zhǎng)度字符編碼,,使用一至四個(gè)字節(jié)為每個(gè)字符編碼:

  •  Unicode范圍為U+0000..U+007F 的128個(gè)ASCII字符只需一個(gè)字節(jié)編碼;
  •  Unicode范圍為U+0080..U+07FF的字符需要二個(gè)字節(jié)編碼,;
  •  Unicode范圍為U+0800..U+FFFF的其他BMP中的字符(這包含了大部分常用字)使用三個(gè)字節(jié)編碼,;
  •  Unicode 輔助平面的字符(其他極少使用的字符)使用四字節(jié)編碼。

        對(duì)上述提及的第四種字符而言,,UTF-8使用四個(gè)字節(jié)來編碼似乎太耗費(fèi)資源了,。但UTF-8對(duì)所有常用的字符都只用三個(gè)字節(jié)表達(dá),而且UTF-16編碼對(duì)前述的第四種字符同樣需要四個(gè)字節(jié)來編碼,,而如果是ASCII居多的字符,,UTF-8能極大的節(jié)約存儲(chǔ)空間。UTF-8逐漸成為電子郵件,、網(wǎng)頁及其他儲(chǔ)存或傳送文字的應(yīng)用中,,優(yōu)先采用的編碼?;ヂ?lián)網(wǎng)工程工作小組(IETF)要求所有互聯(lián)網(wǎng)協(xié)議都必須支持UTF-8編碼,?;ヂ?lián)網(wǎng)郵件聯(lián)盟(IMC)建議所有電子郵件軟件都支持UTF-8編碼,。


        對(duì)CodePoint各個(gè)范圍內(nèi)的字符進(jìn)行UTF-8編碼的規(guī)則如下:

Code point

UTF-8字節(jié)流

U+00000000 – U+0000007F

0xxxxxxx

U+00000080 – U+000007FF

110xxxxx 10xxxxxx

U+00000800 – U+0000FFFF

1110xxxx 10xxxxxx 10xxxxxx

U+00010000 – U+001FFFFF

11110xxx 10xxxxxx 10xxxxxx 10xxxxxx

其中,U+D800到U+DFFF之間的區(qū)段在Unicode字符集的定義中沒有具體字符使用的,,被用來在UTF-16編碼中對(duì)輔助平面的字符進(jìn)行編碼,。


        下面以“田”(Code Point為U+7530)為例,看如何對(duì)其進(jìn)行UTF-8編碼:

  •  U+7530落在U+0800..U+FFFF區(qū)間,,采用三字節(jié)編碼,;
  •  0x7530轉(zhuǎn)換為二進(jìn)制為111 010100 110000
  •  代入表中,,得到111001111001010010110000,;

        這樣,得到“田”(U+7530)的UTF-8編碼:0xE7 94 B0,。


        知道UTF-8的編碼規(guī)則,,我們可以對(duì)于UTF-8編碼中的任意字節(jié)B,進(jìn)行下面解碼:

  •  如果B的第一位為0,,則B為ASCII碼,,并且B獨(dú)立的表示一個(gè)字符;如果B的第一位為1,,第二位為0,,則B為一個(gè)非ASCII字符(該字符由多個(gè)字節(jié)表示)中的一個(gè)字節(jié),并且不為字符的第一個(gè)字節(jié)編碼(字符的第一個(gè)字節(jié)之外的后編碼),;
  •  如果B的前兩位為1,,第三位為0,,則B為一個(gè)非ASCII字符(該字符由多個(gè)字節(jié)表示)中的第一個(gè)字節(jié),并且該字符由兩個(gè)字節(jié)表示,;
  •  如果B的前三位為1,,第四位為0,則B為一個(gè)非ASCII字符(該字符由多個(gè)字節(jié)表示)中的第一個(gè)字節(jié),,并且該字符由三個(gè)字節(jié)表示,;
  •  如果B的前四位為1,第五位為0,,則B為一個(gè)非ASCII字符(該字符由多個(gè)字節(jié)表示)中的第一個(gè)字節(jié),,并且該字符由四個(gè)字節(jié)表示。

 

2.3 UCS-2 vs UTF-16,,UCS-4 vs UTF-32

        UCS-2每個(gè)字符占用2個(gè)字節(jié),。UCS-2是UTF-16的子集。在沒有輔助平面前,,UTF-16與UCS-2所指的是同一的意思,。但當(dāng)引入輔助平面字符后,UTF-16加入了對(duì)輔助平面內(nèi)的字符的支持?,F(xiàn)在若有軟件聲稱自己支持UCS-2編碼,,那其實(shí)是暗指它不支持UTF-16中超過2bytes的字集。亦即,,對(duì)于小于0x10000的UCS碼,,UTF-16編碼就等于UCS碼。Java早期版本對(duì)Unicode的支持,,就只是UCS-2的支持,,現(xiàn)在加入了對(duì)UTF-16的完整支持。

 

        UCS-4UTF-32的意義一致,,對(duì)每個(gè)字符都使用4字節(jié)(31位字符集,,加上恒為0的首位,共需占據(jù)32位),。理論上最多能表示231個(gè)字符,,完全可以涵蓋一切語言所用的符號(hào)。雖然每一個(gè)Code Point使用固定長(zhǎng)定的字節(jié)看似方便,,對(duì)于普通只需要2個(gè)字節(jié)存儲(chǔ)的常用字占絕大對(duì)數(shù)的字符集來說,,卻極大的浪費(fèi)了空間,并沒怎么得到應(yīng)用,。


三,、Big-Endian/Little-Endian與BOM

        在講UTF-16編碼方式時(shí)說到,UTF-16編碼的Code Unit是2個(gè)字節(jié),,這兩個(gè)字節(jié)在傳輸和存儲(chǔ)過程中,,高/低位位置不同,,是不同的字符。比如,,“田”的UTF-16編碼是0x7530,,但是如果存成0x3075,就變成了“ふ”,,成了另外的字符,。

        所以,為了識(shí)別一個(gè)編碼過的字符的存儲(chǔ)順序,,必須用特殊字符來指示,。Unicode字符中U+FEFF被用來指示這種存儲(chǔ)順序,被稱作Byte Order Mark(BOM),。

  •  Big-Endian:最低位地址存放高位字節(jié),,可稱高位優(yōu)先,內(nèi)存從最低地址開始按順序存放(高數(shù)位數(shù)字先寫),。最高位字節(jié)放最前面,。
  •  Little Endian:最低位地址存放低位字節(jié),可稱低位優(yōu)先,,內(nèi)存從最低地址開始按順序存放(低數(shù)位數(shù)字先寫),。最低位字節(jié)放最前面。

        BOM在Big-Endian系統(tǒng)上存儲(chǔ)為FE FF,;而在Big-Endian系統(tǒng)上存儲(chǔ)則為FF FE,。所以在以Big-Endian存儲(chǔ)的UTF-16(UTF-16BE)的文件的開頭,用FEFF指示,;以Little-Endian存儲(chǔ)的UTF-16(UTF-16LE)的文件的開頭,用FFFE指示,。

        BOM的UTF-8編碼為11101111 1011101110111111 (EF BB BF),,所以一般EF BB BF被放在文本的開頭,用來指示其編碼為UTF-8,。

        

四,、Unicode編碼實(shí)踐


        在Windows的文本編輯工具記事本上,選擇“另存為”的時(shí)候,,用戶可以選擇不同的編碼選項(xiàng),,對(duì)應(yīng)編碼選項(xiàng)有“ANSI”,“Unicode”,,“Unicode big endian”,,以及“UTF-8”。因?yàn)閃indows的存儲(chǔ)方式是Little-Endian,,所以“Unicode”,,“Unicode big endian”對(duì)應(yīng)的分別是UTF-16LE和UTF-16BE,。

       

        讀者可以試著編寫一串字符,然后分別用不同的編碼保存,,再用可以16進(jìn)制編寫的純文本編輯工具(如,,Ultra-edit)來檢驗(yàn)一下具體的編碼實(shí)現(xiàn)和存儲(chǔ)順序。下面是筆者將“田海立(U+7530, U+6D77, U+7ACB)”以不同編碼方式保存,,得到的結(jié)果:

田海立_UTF-16BE.txt

        FEFF75306D777ACB

田海立_UTF-16LE.txt

        FFFE3075776DCB7A

田海立_UTF-8.txt

        EFBBBFE794B0E6B5B7E7AB8B

        為了明確起見,,BOM的編碼用粗體標(biāo)注;田的編碼用紅色標(biāo)注,;海的編碼用綠色標(biāo)注,;立的編碼用藍(lán)色標(biāo)注??梢钥吹?,記事本(Notepad)存儲(chǔ)的Unicode編碼的文件的開頭位置,用BOM的相應(yīng)編碼指示了編碼格式,。


【后記】歷史

        最近需要用到Unicode的編碼實(shí)現(xiàn)方式,,又收集了一下資料。發(fā)現(xiàn)早在06年的時(shí)候,,筆者就準(zhǔn)備總結(jié)一下Unicode的編碼實(shí)現(xiàn),,文檔里也已經(jīng)有了提綱。現(xiàn)在也不記得當(dāng)時(shí)什么原因給耽擱了,,好在現(xiàn)在及時(shí)總計(jì)歸納,。好腦子不如爛筆頭啊。如果當(dāng)初總結(jié)下來,,現(xiàn)在也不用再浪費(fèi)時(shí)間收集資料,。

        希望,這次的總結(jié)能比較完善,,以后再用到Unicode編碼,,只要參考此文即可!(當(dāng)然前提是Unicode標(biāo)準(zhǔn)別又演進(jìn)了^_^)


【附】基本概念對(duì)照

  1. Code Point代碼點(diǎn)或碼位
  2. Code Unit代碼單元或碼元,,是指一個(gè)已編碼的文本中具有最短的比特組合的單元,。對(duì)于UTF-8來說,碼元是8比特長(zhǎng),;對(duì)于UTF-16來說,,碼元是16比特長(zhǎng);對(duì)于UTF-32來說,,碼元是32比特長(zhǎng),。
  3. BMP - Basic Multilingual Plane
  4. UTF - Unicode Transformation Format
  5. BOM – Byte Order Mark
  6. UCS - Universal Character Set

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,,不代表本站觀點(diǎn),。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式,、誘導(dǎo)購買等信息,謹(jǐn)防詐騙,。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶 評(píng)論公約

    類似文章 更多