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