UTF-16 - 字嗨!

文章推薦指數: 80 %
投票人數:10人

因為處理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分關於本站|關於字碼資料庫



請為這篇文章評分?