前端培訓-中級階段(16)- Unicode和UTF編碼(2019-09-12期)

前端最基礎的就是 HTML+CSS+Javascript。掌握了這三門技術就算入門,但也僅僅是入門,現在前端開發的定義已經遠遠不止這些。前端小課堂(HTML/CSS/JS),本着提升技術水平,打牢基礎知識的中心思想,我們開課啦(每週四)。

編碼解碼對於web開發來說,有可能最常見的是URL編碼(encode decode)。

ASCII 編碼

計算機處理的內容是二進制,對應開和關的狀態。如果要處理文本,也是把文本轉換爲數字然後做比對。最早的計算機在設計時採用8個比特(bit)作爲一個字節(byte)
一個字節能表示的最大的整數就是2550b11111111==255)。這255個數字被用來表示大小寫英文字母、數字和一些符號,這個編碼表被稱爲ASCII編碼,比如大寫字母A的編碼是65,小寫字母a的編碼是97。

ASCII 對照表

GB2312編碼

如果要表示中文,顯然ASCII的一個字節是不夠的,至少需要兩個字節,而且還不能和ASCII編碼衝突。
所以,中國製定了GB2312編碼(國標2312編碼),用來把中文編進去。

Unicode 編碼

Unicode(萬國碼),包括字符集、編碼方案等。
Unicode 是爲了解決傳統的字符編碼方案的侷限而產生的,它爲每種語言中的每個字符設定了統一併且唯一的二進制編碼,以滿足跨語言跨平臺進行文本轉換、處理的要求。1990年開始研發,1994年正式公佈。
Unicode通常用兩個字節表示一個字符原有的英文編碼從單字節變成雙字節,只需要把高字節全部填爲0就可以。目前的Unicode字符集爲0x00000x10FFFF,分爲17組編排,,每平面擁有65536個碼位,共1114112個碼位

Unicode 到目前爲止所定義的十七個平面中,第0平面(BMP)最爲重要。

中文範圍 4E00-9FA5:CJK 統一表意符號 (CJK Unified Ideographs)

Unicode中:“李”字對應的數字是26446(十進制),十六進制表示爲0x674e

UTF 編碼系列

Unicode 只是一個大的合集,UTF-8UTF-16UTF-32纔是將數字轉換到程序數據的編碼方案。
UTFUnicode Transformation Format的縮寫,可以翻譯成Unicode字符集轉換格式,即怎樣將Unicode定義的數字轉換成程序數據。

UTF-8

UTF-8的特點是對不同範圍的字符使用不同長度的編碼,這點極大的縮小了文件的大小。當然,也會造成一定的性能浪費,

對於0x00-0x7F之間的字符,UTF-8編碼與ASCII編碼完全相同。
對於超過區間的字符,最高位非0,10標識當前屬於前面字節的描述字節。110標明這是兩個字節的,後面還會跟着一個字節。

UTF-8編碼的最大長度是4個字節。從表格中可以看到,4字節模板有21個x,即可以容納21位二進制數字。Unicode的最大碼位0x10FFFF也只有21位。

Unicode編碼(十六進制) UTF-8 字節流(二進制)
000000-00007F 0xxxxxxx
000080-0007FF 110xxxxx 10xxxxxx
000800-00FFFF 1110xxxx 10xxxxxx 10xxxxxx
010000-10FFFF 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
“李” \u674e 11100110 10011101 10001110
“A” \u0041 01000001

UTF-16

UTF-16編碼以16位無符號整數爲單位。我們把Unicode編碼記作U。
如果U<0x10000,UTF-16編碼(二進制)就是對應的16位無符號整數。
如果U≥0x10000,先計算U'=U-0x10000,然後將U'寫成二進制形式:yyyy yyyy yyxx xxxx xxxx,U的UTF-16編碼(二進制)就是:110110yyyyyyyyyy 110111xxxxxxxxxx

這裏,你會好奇,因爲第二條規則會和第一條規則重複。爲了將編碼區分開來,Unicode編碼的設計者將0xD800-0xDFFF保留下來,並稱爲代理區(Surrogate)

// D800-DB7F    High Surrogates    高位替代
// 指UTF-16編碼中。兩個位置中的第一個位置
(0xD800).toString(2) == 1101100000000000
(0xDB7F).toString(2) == 1101101101111111

// DC00-DFFF    Low Surrogates     低位替代
// 指UTF-16編碼中。兩個位置中的第二個位置
(0xDC00).toString(2) == "1101110000000000"
(0xDFFF).toString(2) == "1101111111111111"

// DB80-DBFF    High Private Use Surrogates      高位專用替代
(0xDB80).toString(2) == "1101101110000000"
(0xDBFF).toString(2) == "1101101111111111"

UTF-32

UTF-32編碼以32位無符號整數爲單位。Unicode的UTF-32編碼就是其對應的32位無符號整數。

字節序

字節序有兩種,分別是“大端”(Big Endian, BE)和“小端”(Little Endian, LE)。
根據字節序的不同,UTF-16可被實現爲UTF-16LE或UTF-16BE,UTF-32可被實現爲UTF-32LE或UTF-32BE。

Unicode編碼 UTF-16LE UTF-16BE UTF32-LE UTF32-BE
0x006C49 49 6C 6C 49 49 6C 00 00 00 00 6C 49
0x020C30 43 D8 30 DC D8 43 DC 30 30 0C 02 00 00 02 0C 30

Unicode標準建議用BOM(Byte Order Mark)來區分字節序,即在傳輸字節流前,先傳輸被作爲BOM的字符“零寬無中斷空格”。這個字符的編碼是FEFF,而反過來的FFFE(UTF-16)和FFFE0000(UTF-32)在Unicode中都是未定義的碼位,不應該出現在實際傳輸中。

UTF編碼 Byte Order Mark (BOM)
UTF-8 without BOM
UTF-8 with BOM EF BB BF
UTF-16LE FF FE
UTF-16BE FE FF
UTF-32LE FF FE 00 00
UTF-32BE 00 00 FE FF

URL編碼/解碼

url編碼是一種瀏覽器用來打包表單輸入的格式
瀏覽器將表單中獲取到的內容,以name=value參數編碼,作爲URL的一部分或者放入body發給服務器。轉換成如:a=1&b=2

基於上面的規則,=或者&都會造成解析異常。所以特殊的字符(不是簡單的七位ASCII,如漢字,關鍵詞),會以%XX這個格式轉義,比如:

字符 encode編碼 utf-8編碼
= %3D 00111101
%E6%9D%8E 11100110 10011101 10001110
// 轉換代碼
encodeURIComponent('李').replace(/%([0-9a-f]{2})/gi, (v,group1)=>parseInt(group1,16).toString(2)+' ') // "11100110 10011101 10001110 "
encodeURIComponent('=').replace(/%([0-9a-f]{2})/gi, (v,group1)=>parseInt(group1,16).toString(2).padStart(8,'0')+' ') //"00111101 "

微信公衆號:前端linong

clipboard.png

參考文獻

  1. 前端培訓目錄、前端培訓規劃、前端培訓計劃
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章