編碼方式的簡介(ASCII, LATIN
編碼方式的簡介
1. ASCII
ASCII是7比特的字符集,涵蓋了英語中的絕大多數字元。編碼從0到127.
2.ISOLatin-1(the ISO-8859-1 standard)
ISO Latin-1是8比特的字符集,定義了256個字元。前128個字元(00000000-01111111)與ASCII完全一致。
3. Unicode
Unicode只是定義了字元的編碼值,並未指定值以何種形式存儲。比如漢字「田」的Unicode編碼是7530,轉換為二進位是01110101,00110000。比方現在定義一種unicode的實現方式UTF-FAKE,規則是
a.使用24個位元組
b.每個位元組的高7位都是1
c.每個位元組的最末一位存儲unicode編碼值
那麼01110101,00110000的存儲形式是
11111110, 11111110, 11111110, 11111110, 11111110, 11111110, 11111110, 11111110,
11111110, 11111111, 11111111, 11111111, 11111110, 11111111, 11111110, 11111111,
11111110, 11111110, 11111111, 11111111, 11111110, 11111110, 11111110, 11111110
其中末位為藍色0的位元組為補足位元組。
實際使用的編碼方式UTF-8使用三個位元組存儲「田」 01110101,00110000,如下
11100111, 10010100, 10110000
Unicode的第一個版本於1991年發布,該版本允許的的最大編碼空間是兩個位元組。96年發布的Unicode 2.0版本引入了surrogate pair,將Unicode的編碼數目擴充到了百萬級,由於可見的將來該數目不大可能用光,因此Unicode委員會對外宣稱該上限永不會更改。Surrogate pair在UTF-16和UTF-32中得到了實現。Unicode的前256個字元及編碼值與Latin-1完全一致。比如大寫字母A在Latin-1和Unicode中的編碼值都是0x41(十進位的65)。
Unicode的編碼值範圍是000000hex到10FFFFhex,可劃分為17個plane,每個plane包含65536(= 216)個字元。Plane的代碼從0到16(十進位),對應於000000hex,010000hex,020000hex,… … ,0F0000hex,10FFFFhex的藍色部分。
Unicode的表示方式一般是」U 」後綴上4到6個十六進位字元,如」田「的Unicode表示方式是U 7530。
4. UTF-8
UTF-8採用可變長度的編碼,長度從1到4個位元組不等。某些應用識別非標準的"utf8" 或"UTF 8"別名。只有ASCII字元在UTF-8中使用一個位元組編碼,且值與ASCII完全相同,其餘字元在UTF-8中使用2到4個位元組。因此UTF-8中的單位元組且只有單位元組編碼字元的最高的1個比特是0。
UTF-8對Unicode字元的編碼規則如下
Bits ofcode point |
Firstcode point |
Lastcode point |
Bytes insequence |
Byte 1 |
Byte 2 |
Byte 3 |
Byte 4 |
7 |
U 0000 |
U 007F |
1 |
|
|||
11 |
U 0080 |
U 07FF |
2 |
|
|
||
16 |
U 0800 |
U FFFF |
3 |
|
|
|
|
21 |
U 10000 |
U 1FFFFF |
4 |
|
|
|
|
說明如下:
1.只有ASCII使用單位元組編碼
2.Unicode編碼值大於127的字元使用多個位元組編碼。多位元組序列的第一個位元組稱為leading byte,後續的位元組稱為continuation bytes。Leading byte的高位是110,1110或11110,其中的「1」的個數標明了序列中的位元組總數。如2個位元組序列的leading byte為11
0xxxxx
,其中的11
標明了這是一個雙位元組的序列,亦即該序列有1個continuation byte。Continuation bytes的每個位元組的高兩位均是10。
3.單位元組序列、leading bytes和continuationbytes的高位分別是0,110/1110/11110和10,因此不會混淆。
還是以漢字」田「為例,展示Unicode字元如何按照UTF-8存儲。」田「的Unicode值是U 7530,比對上表發現介於U 0800 - U FFFF之間,因此需要3個位元組來存儲。7530轉為二進位是1110101,00110000,一共15位。但由於UTF-8的3位元組編碼存儲16個比特,因此將1110101,00110000的高一位補零變成16比特01110101,00110000。然後將這16比特依次填入三位元組序列1110xxxx 10xxxxxx 10xxxxxx的x中,得到結果
11100111 10010100 10110000,寫成16進位就是E7 94 B0
注意:雖然Unicode中的前256個字元及編碼值與Latin-1完全一致,但UTF-8隻對前128個即ASCII字元採用單位元組編碼,其餘128個Latin-1字元是採用2個位元組編碼。因此ASCII編碼的文件可以直接以UTF-8方式讀取,而Latin-1的文件若包含值為128-255的字元則不可以。
5. UTF-16
UTF-16也是採用可變長度編碼,可以是一個或者兩個16比特。某些應用中允許使用非標準的UTF_16或者UTF16作為別名。Unicode中的第一個plane的65536(= 216)codepoints採用16比特編碼,其餘的16個plane均採用2個16比特編碼。採用2個16比特編碼的前後兩個16bit分別稱為lead surrogate pair和trail surrogate pair,之所以稱為surrogate是因為單獨一個16bit不代表任何字元,只有組合起來才有意義。
既然UTF-16也是可變長度編碼,如何區分某個16bit是單獨表示一個字元還是與後續的16bit組合起來表示一個字元呢?Unicode將D800–DBFF和DC00–DFFF這兩個範圍作為保留區間,沒有將之分配給任何Unicode字元,若某16比特落在D800–DBFF範圍內,便可將之視為採用2個16bit編碼字元的第一個16bit,而落在DC00–DFFF的16bit可視為採用2個16bit編碼字元的第二個16bit。這就使得Unicode第一個plane實際可分配使用的code points只有65536 – (DFFF - D800 1) = 65536 – 8*256 = 63488。
採用一個16bit編碼的Unicode字元在UTF-16中的編碼值與其在Unicode中是相等的,比如英文大寫字母A的Unicode值是U 0041,其UTF-16編碼是0041 hex。Unicode第二到第十七個plane採用兩個16bit即surrogate pairs的字元從其Unicode code point到UTF-16的轉換規則是
1. 範圍為0x10000 … 0x10FFFF的codepoint減去0x010000,減過後的結果範圍是0x00000到0xFFFFF,使得該結果可以使用5位16進位亦即20位2進位數表示
2. 結果中高10位(範圍是0x0到0x3FF)加上0xD800(結果範圍是0xD800到0xDBFF)作為雙16bit的第一個16bit即leadsurrogate
3. 結果中低10位(範圍是0x0到0x3FF)加上0xDC00(結果範圍是0xDC00到0xDFFF)作為雙16bit的第二個16bit即trailsurrogate
這樣UTF-16與UTF-8都是self-synchronizing的,即某個16bit是否是一個字元的開始無需檢查其前一個或者後一個16bit。與UTF-8的不同之處是,UTF-16不支持從某個隨機的位元組開始讀取。
舉例:UTF-16序列0041,D801DC01 (字元"A
"),若第一個位元組丟失即從第二個位元組讀取,那麼UTF-16認為序列是41D8,01DC,01;而UTF-8不存在這個問題。
BOM(byte-order mark)
BOM是Unicode中用來標識位元組順序的字元。
對於UTF16和UTF32,由於編碼單元分別是16bit和32bit,即2個和4個位元組,編碼單元內位元組的順序就取決於計算機的體系結構。以英文大寫字母A和漢字田為例,大端(big endianness,縮寫為BE)和小端(littleendianness,縮寫為LE)存儲的位元組序列是
UTF-16BE |
UTF-16LE |
UTF-32BE |
UTF-32BE |
|
A |
00,41 |
41,00 |
00,00,00,41 |
41,00,00,00 |
田 |
75,30 |
30,75 |
00,00,75,30 |
30,75,00,00 |
BOM就是用來標識編碼使用的是大端還是小端存儲,該符號位於文本序列起始位元組之前。
UTF-8
UTF-8中的BOM是0xEF,0xBB,0xBF。Unicode標準裡面允許UTF-8使用BOM,但並不要求也不鼓勵使用。由於UTF8編碼單位是位元組,位元組的先後順序在編碼、傳輸和解碼過程中均不改變,因此不存在endianness。BOM在UTF8中的唯一作用是標識序列使用的是UTF8編碼,在由其它使用BOM的編碼轉換為UTF8編碼的情況下,建議在UTF8序列中保留BOM以便轉換回原編碼的時候不丟失BOM信息。
接下來看看用Notepad 的HEX-Editor插件查看的文件16進位的編碼。
文件中僅包含一個英文大寫字母A,其Unicode編碼值是U 0041。
使用UTF-8(預設包含BOM),位元組序列是ef bb bf 41
使用不帶BOM的UTF-8,位元組序列是 41。
UTF-16
UTF-16中bigendianness和littleendianness的BOM分別是U FEFF和U FFFE。可以使用編碼方式UTF-16BE和UTF-16LE來顯式地標明位元組順序,當使用了UTF-16BE和UTF-16LE時,BOM不應該再出現在位元組序列中,很多應用直接忽略該字元若其仍然存在。
由於Notepad 不支持UTF16編碼,因此下面的截圖中使用了UTF-16的前身UCS-2來替代。UCS-2對Unicode的第一個plane的編碼與UTF-16相同,都是1個16bit,且編碼結果相同。
UTF-32
UTF32中的bigendianness和littleendianness的BOM分別是0000FEFF和FFFE0000。
總結五種編碼方式的BOM依次是
BOM |
編碼方式 |
00 00 FE FF |
UTF-32, big-endian |
FF FE 00 00 |
UTF-32, little-endian |
FE FF |
UTF-16, big-endian |
FF FE |
UTF-16, little-endian |
EF BB BF |
UTF-8 |
推薦閱讀:
※編碼歪傳
※業力與大腦神經編碼記憶 腦可塑性-大腦皮層增大-記憶學習經歷固化 大腦重構 關鍵期MeCP2蛋白 中風大腦修復
※深度學習進修之旅
※應該學習編碼的5個理由
※iOS KVO crash 自修復技術實現與原理解析