UTF-16 - 字嗨!
文章推薦指數: 80 %
因為處理UTF-16兩種編碼序列時如果搞錯,會得到完全不同的結果,所以UTF-16純文字文件習慣在前面加上U+FEFF 字元作為BOM(Byte Order Mark;位元組順序標註)。
字碼漢字登入
UTF-16📄💬
UTF-16是Unicode的一種可變長度的字元編碼形式。
它原來是最早期Unicode1.0所想像,能用16位元的固定長去處理全世界所有文字的UCS-2。
但自從Unicode2.0新增補充平面後,16位元已經不足以表示Unicode內所有文字。
所以UTF-16又設計了「代理對」的機制,以兩個16位元的組合去表達補充平面的文字。
這讓UTF-16實質上也是一種可變長度的編碼方式。
編碼方式
基本多語言平面內的文字,Unicode碼位本身的值就是正確的UTF-16。
意即U+8140腀的UTF-16值就是0x8140。
代理對(surrogatepairs)
Unicode2.0決定擴充原來的基本多語言平面,新增補充平面後,同時決定將U+D800到U+DFFF的碼位空下來,專作為UTF-16的代理字元使用。
凡是補充平面(即,非基本多語言平面的其他所有平面)的文字,就必須進行轉換,改以兩個代理字元組成。
代理對計算方式
以U+1F63C😼為例:
0x1F63C減去0x10000,結果為0x0F63C,二進位為00001111011000111100共20位。
將他的二進位前方10位數0000111101(0x03D)加上0xD800形成高位0xD83D。
將他的二進位後方10位數1000111100(0x23C)加上0xDC00形成低位0xDE3C。
以U+2C9B0𬦰為例
0x2C9B0減去0x10000,結果為0x1C9B0,二進位為00011100100110110000共20位。
將他的二進位前方10位數0001110010(0x072)加上0xD800形成高位0xD872。
將他的二進位後方10位數0110110000(0x1B0)加上0xDC00形成低位0xDDB0。
編碼序列
因為遙遠的歷史因素,各機器、作業系統處理16位元序列的順序都不一致。
例如Windows與Linux習慣使用LittleEndian(低位在前);而TCP/IP、Java虛擬機器等習慣使用BigEndian(高位在前)。
由於UTF-16是16位元編碼方式,也受到位元序列的影響,有UTF-16BE、UTF-16LE兩種序列形式。
碼位UTF-16UTF-16BEUTF-16LE
U+0041A004100414100
U+20AC€20AC20ACAC20
U+2C9B0𬦰D872DDB0D872DDB072D8B0DD
請注意UTF-16BE與UTF-16LE的差異與代理對無關,而是每一個16位元序列之內的順序問題。
BOM
因為處理UTF-16兩種編碼序列時如果搞錯,會得到完全不同的結果,所以UTF-16純文字文件習慣在前面加上U+FEFF字元作為BOM(ByteOrderMark;位元組順序標註)。
在UTF-16BE序列上會是FEFF的序列,UTF-16LE序列上則是FFFE的序列,以便檢查文件的序列方式。
U+FEFF字元本身的定義是不占空間也不換行的空格,所以理論上忽略BOM的處理,仍然不會影響到文件內容的正常解讀與處理。
另外,依照UTF-8的規格,UTF-8序列中不會出現0xFF與0xFE的位元組,所以正好用來標示這是UTF-16文件。
使用環境
相較於UTF-8,雖然UTF-16的漢字只佔2bytes,但所有ASCII字元也都佔用2bytes的關係,所以平均而言會更佔空間。
但因為UTF-16原先是固定長度的,對程式處理而言,16位元固定長度雖然會浪費一些儲存空間,但能帶來計算快速之類的好處(例如字串的切割、尋找第N個字,可以直接存取到正確位置,不需要從序列前方尋找),但隨著補充平面與代理對的出現,此優點已經消失。
故UTF-16主要使用在1996年之前(Unicode1.0時代還沒有補充平面的時代)第一批支援Unicode的環境,例如Windows系統API、Java虛擬機器、Python2、JavaScript等。
這些實作很多到現在仍然將代理對視為兩個字處理,造成程式處理Emoji、擴充漢字時的困擾。
參考
UTF-8
UTF-32
基本多語言平面
補充平面
建立於2022年3月15日21時44分本條目共被1位不同作者編輯過2次最後一次修改於2022年3月16日01時22分關於本站|關於字碼資料庫
延伸文章資訊
- 1FAQ - UTF-8, UTF-16, UTF-32 & BOM - Unicode
Where the data has an associated type, such as a field in a database, a BOM is unnecessary. In pa...
- 2utf-16le[BOM] to utf-8 file solution - GitHub
http://stackoverflow.com/questions/22459020/python-decode-utf-16-file-with-bom. import codecs. en...
- 3UTF-16 - 維基百科,自由的百科全書
以下的例子有四個字元:「朱」(U+6731)、半形逗號(U+002C)、「聿」(U+807F)、「𪚥」(U+2A6A5)。 使用UTF-16編碼的例子. 編碼名稱, 編碼次序, 編碼. BOM,...
- 4位元組順序記號 - 维基百科
位元組順序記號(英語:byte-order mark,BOM)是位於碼點 U+FEFF 的統一碼字符的名称。當以UTF-16或UTF-32來將UCS/統一碼字符所組成的字串編碼時,這個字符被用來...
- 5UTF-16 - 字嗨!
因為處理UTF-16兩種編碼序列時如果搞錯,會得到完全不同的結果,所以UTF-16純文字文件習慣在前面加上U+FEFF 字元作為BOM(Byte Order Mark;位元組順序標註)。