摘要:最近在看書的時(shí)候突然糾結(jié)于相關(guān)字符編碼,查了一些資料,并寫了這篇文章,順帶做下筆記,希望能幫到一些人。解決傳統(tǒng)的字符編碼方案的局限。
最近在看書的時(shí)候突然糾結(jié)于Unicode相關(guān)字符編碼,查了一些資料,并寫了這篇文章,順帶做下筆記,希望能幫到一些人。文章如果有寫的不妥的或者不正確的地方還請大家糾正。
Unicode 編碼Unicode是一個符號集,它對世界上大部分的文字系統(tǒng)進(jìn)行了整理、編碼,使得電腦可以用更為簡單的方式來呈現(xiàn)和處理文字。解決傳統(tǒng)的字符編碼方案的局限。
歷史上存在兩個獨(dú)立的嘗試創(chuàng)立單一字符集的組織,即國際標(biāo)準(zhǔn)化組織(ISO)和非營利機(jī)構(gòu)統(tǒng)一碼聯(lián)盟。前者開發(fā)的 ISO/IEC 10646 項(xiàng)目,后者開發(fā)的統(tǒng)一碼項(xiàng)目。因此最初制定了不同的標(biāo)準(zhǔn)。他們不久便發(fā)現(xiàn)對方的存在,大家為著相同的目的而工作,最后他們合并雙方的工作成果。統(tǒng)一碼(Unicode)的編碼方式與ISO 10646的通用字符集(Universal Character Set, 簡稱UCS)概念相對應(yīng)。
統(tǒng)一碼的編碼方式使用16位編碼空間,也就是每個字符占用2個字節(jié),最多可表示2^(16)個字符,基本滿足各種語言的需求,且實(shí)際上16為編碼空間并未完全使用,其中保留了大量空間作為未來備用。這里所說的16位編碼空間即統(tǒng)一碼的0號平面(也稱“基本多文種平面”,Basic Multilingual Plane,簡稱BMP),目前統(tǒng)一碼版本中另外定義了16個輔助平面,這樣就需求21位編碼空間,即 16+5 位,一共17個平面(不局限于),每個平面擁有2^(16)個代碼點(diǎn)。如下表所示(摘自Wikipedia):
ASCIIASCII(“阿斯柯”) 是國際上普遍采用的一種字符編碼系統(tǒng),由8位二進(jìn)制進(jìn)行編碼,最高位恒為0,因此可以定義128個字符,其中包括10個十進(jìn)制數(shù)字、52個英文大小寫字母(A~Z, a~z)等。
UTF-8UTF(Unicode Transformation Format, Unicode字符集轉(zhuǎn)換格式),UTF-7、UTF-8、UTF-16、UTF-32、GB18030...只是Unicode的一種實(shí)現(xiàn)方式,即怎樣將 Unicode 定義的數(shù)字轉(zhuǎn)換成程序數(shù)據(jù)。
UTF-8 編碼,以8位無符號整數(shù)為單位進(jìn)行編碼,是針對Unicode的可變長字符編碼,UTF-8 是 ASCII 編碼的父集,也就是說,UTF-8 與 ASCII 編碼兼容,如:對于0x000000-0x00007F之間的字符,即前128個字符,UTF-8 編碼與 ASCII 編碼完全相同。這使得原來處理 ASCII 碼字符的軟件無須或只須做少部分修改,即可繼續(xù)使用,UTF-8 編碼應(yīng)用廣泛,基本所有互聯(lián)網(wǎng)協(xié)議都支持 UTF-8 編碼,是目前編碼方式中優(yōu)先采用的方式之一。
關(guān)于Unicode 與 UTF-8 編碼之間的轉(zhuǎn)換關(guān)系,如下表所示:
在基本多文種平面中約定00D800-00DFFF這范圍用于UTF-16擴(kuò)展標(biāo)識輔助平面(即低位兩個字節(jié)),在UTF-16 中會詳細(xì)介紹。
舉個例子,漢字“聽”的 Unicode 編碼是U+542C,轉(zhuǎn)成UTF-8,步驟如下:
由上表可得出,“聽”字的 Unicode 編碼屬于U+0800到U+D7FF區(qū)域,說明該字占用3個字節(jié),按照1110xxxx-10xxxxxx-10xxxxxx進(jìn)行填充。
U+542C換算成二進(jìn)制:0101-0100-0010-1100。
從低位向高位填充,代替x,11100101-10010000-10101100。
得出漢字“聽”的UTF-8編碼:0xE590AC。
從Unicode 2.0開始,Unicode采用了與ISO 10646-1相同的字庫和字碼;ISO也承諾,ISO 10646將不會替超出U+10FFFF的UCS-4編碼賦值,以使得兩者保持一致。2003年11月 UTF-8 被 RFC 3629重新規(guī)范,只能使用原來Unicode定義的區(qū)域,U+0000到U+10FFFF。如果以上都能理解,那么下表就非常好理解了(摘自Wikipedia):
UTF-8 小結(jié)
在UTF-8文件的開首,以EF,BB,BF代表,以顯示這個文本文件是以UTF-8編碼。
字節(jié)0xFE和0xFF在UTF-8編碼中從未用到,同時(shí),UTF-8以字節(jié)為編碼單元,它的字節(jié)順序在所有系統(tǒng)中都是一様?shù)?,沒有字節(jié)序的問題,也因此它實(shí)際上并不需要BOM(字節(jié)順序標(biāo)記,Byte-Order Mark),但在UTF-16中用來標(biāo)記存儲方式(大端小端)。
ASCII和UTF-8兩種編碼方式下是一樣的,可以說UTF-8是ASCII編碼的父集。
現(xiàn)在我們已經(jīng)知道了UTF-8的含義,以及其編碼原理,下面我們來探究一下 UTF-16 編碼方式。
UTF-16UTF-16 編碼,以16位無符號整數(shù)為單位進(jìn)行編碼。上文中所提及到的“基本多文種平面”的編碼空間中保留了一塊區(qū)域(從U+D800到U+DFFF),該區(qū)域不映射Unicode字符,UTF-16就是利用保留下來的0xD800-0xDFFF編碼空間來對U+10000到U+10FFFF(即輔助平面)進(jìn)行字符映射的。
在 UTF-16 編碼中,從U+0000至U+D7FF以及從U+E000至U+FFFF的編碼空間的映射關(guān)系同 Unicode,相對應(yīng)于ISO通用字符集中的USC-2。從U+10000到U+10FFFF的編碼空間,UTF-16用一對16比特長的碼元(即32bit,4Bytes)進(jìn)行編碼,熟稱代理對(Surrogate Pair).
0xD800-0xDFFF編碼空間分成兩部分(即上述所說的代理對):
UTF-16的高位代理:從U+D800至U+DBFF,也稱前導(dǎo)代理(lead surrogates)。
UTF-16的低位代理:從U+DC00至U+DFFF,也稱后尾代理(trail surrogates)。
UTF-16 輔助平面編碼方式比較巧妙,從U+10000到U+10FFFF,共計(jì)FFFFF個,即2^(20)個,至少需要20位來表示,我們再來看代理對,先看高半?yún)^(qū),從U+D800到U+DBFF,共計(jì)3FF個,即2^(10)個,同理低半?yún)^(qū)也是2^(10)個,正好為2^(20)個代理對,這也是“基本多語言平面”中保留不對應(yīng)于Unicode字符的2048個碼位的原因。下面我們來看一張表:
舉個例子,古意大利字母"?"的Unicode編碼為U+10300,轉(zhuǎn)成UTF-16,步驟如下:
在0x10300的基礎(chǔ)上先減去0x10000 --> 0x00300,轉(zhuǎn)成二進(jìn)制:0000-0000-0011-0000-0000。
得出高10位(0000-0000-00)和低10位(11-0000-0000)
添加0xD800到高10位(不足補(bǔ)0),得出UTF-16高位:0xD800 + 0x0000 --> 0xD800
添加0xDC00到低10位(不足補(bǔ)0),得出UTF-16低位:0xDC00 + 0x0300 --> 0xDF00
得出古意大利字母"?"的UTF-16BE編碼:U+D800DF00
關(guān)于Unicode 與 UTF-16 編碼之間的轉(zhuǎn)換關(guān)系,如下表所示:
由上表可看出,UTF-16無法兼容ASCII編碼。
UTF-16 存儲形式
想必讀者現(xiàn)在有這樣一個疑惑,UTF-16 是以16位無符號整數(shù)位單位進(jìn)行編碼,即每個字符占用兩個字節(jié),如:在Mac和Window上,對字節(jié)順序的理解是不一樣的,這時(shí)就出現(xiàn)了一個問題,同一字節(jié)流可能會被解釋為不同內(nèi)容,以字符“心“為例,該字符十六進(jìn)制編碼為U+5FC3,按兩個字節(jié)進(jìn)行拆分:5F和C3,在Mac上讀取時(shí)是從低字節(jié)開始,那么在Mac OS會認(rèn)為此U+5FC3編碼為U+C35F,顯示字符為"?",而在Windows上從高字節(jié)開始讀取,則編碼為U+5FC3的字符為“心”。為了解決該問題,字節(jié)順序標(biāo)記(Byte-Order Mark, BOM)誕生,字符U+FEFF如果出現(xiàn)在字節(jié)流的開頭,則用來標(biāo)識該字節(jié)流的字節(jié)序,是高位在前還是低位在前,反之同理。這兩種字節(jié)序在計(jì)算機(jī)我們通常稱大端和小端,下面我們來繼續(xù)探究一下。
大端存儲(Big Endian, 簡稱BE):一個字中的高位字節(jié)放在內(nèi)存中這個字區(qū)域的低地址。小端存儲(Little Endian, 簡稱LE):即一個字中的低位字節(jié)放在內(nèi)存中這個字區(qū)域的低地址處。
還是以古意大利字母"?"為例,我們剛已計(jì)算出其UTF-16編碼為U+D800DF00,如果采用大端存儲,編碼存儲的序列為D800 DF00,采用小端存儲,則為00D8 00DF。這個兩個存儲模式的區(qū)別在于字中字節(jié)的存儲順序不同,而字的存儲順序是相同的。再看幾個例子(摘自Wikipedia):
UTF-16 小結(jié)
在UTF-16文件的開首,以FEFF 或者 FFFE代表,以顯示這個文本文件是以BE存儲編碼還是以LE存儲編碼。
UTF-16編碼可以說是UCS-2的父集,對于小于0x10000的Unicode碼,UTF-16編碼就等于UCS碼,也可以說UTF-16編碼就等于Unicode標(biāo)量值。
UTF-16 VS UTF-8,個人覺得這兩種編碼方式?jīng)]有可比性,主要取決于字符本身主要集中在哪個平面,兩者都是可變長度編碼。
UTF-16 VS UCS-21,如果這個字超過U+FFFF(如:U+10000至U+10FFFF),那么就無法用UCS-2的格式編碼,UTF-16可看成是UCS-2的父集。
相關(guān)文章及鏈接字符編碼筆記:ASCII,Unicode和UTF-8
Unicode Wikipedia
UTF-8 Wikipedia
字節(jié)順序標(biāo)記 Wikipedia
UTF-16 Wikipedia
Unicode 字符平面映射
UCS即ISO 10646的通用字符集(Universal Character Set, 簡稱UCS),UCS-2我們可以簡單理解為UTF-16,同樣使用16位的編碼空間。 ?
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/66585.html
摘要:對象源碼結(jié)構(gòu)如下對象類型對象編碼引用統(tǒng)計(jì)指向底層實(shí)現(xiàn)數(shù)據(jù)結(jié)構(gòu)的指針字段對象類型,就是我們常說的。。對象編碼對應(yīng)跳躍表壓縮列表集合動態(tài)字符串等八種底層數(shù)據(jù)結(jié)構(gòu)。 相信很多人應(yīng)該都知道 Redis 有五種數(shù)據(jù)類型:字符串、列表、哈希、集合和有序集合。但這五種數(shù)據(jù)類型是什么含義?Redis 的數(shù)據(jù)又是怎樣存儲的?今天我們一起來認(rèn)識下 Redis 這五種數(shù)據(jù)結(jié)構(gòu)的含義及其底層實(shí)現(xiàn)。 首先要明確...
閱讀 454·2019-08-29 12:44
閱讀 3035·2019-08-26 17:49
閱讀 2489·2019-08-26 13:40
閱讀 1202·2019-08-26 13:39
閱讀 3684·2019-08-26 11:59
閱讀 1846·2019-08-26 10:59
閱讀 2490·2019-08-23 18:33
閱讀 2718·2019-08-23 18:30