UTF-16是Unicode字符集的一種轉換方式,即把Unicode的碼位轉換為16比特長的碼元串行,以用於數據存儲或傳遞。UTF-16編碼規則如下:
2.2.1 從U+D800到U+DFFF的碼位(代理區)
因為Unicode字符集的編碼值范圍為0-0x10FFFF,而大於等於0x10000的輔助平面區的編碼值無法用2個字節來表示,所以Unicode標准規定:基本多語言平面內,U+D800..U+DFFF的值不對應於任何字符,為代理區。因此,UTF-16利用保留下來的0xD800-0xDFFF區段的碼位來對輔助平面的字符的碼位進行編碼。
但是在使用UCS-2的時代,U+D800..U+DFFF內的值被占用,用於某些字符的映射。但只要不構成代理對,許多UTF-16編碼解碼還是能把這些不符合Unicode標准的字符映射正確的辨識、轉換成合規的碼元. 按照Unicode標准,這種碼元串行本來應算作編碼錯誤.
2.2.2 從U+0000至U+D7FF以及從U+E000至U+FFFF的碼位
第一個Unicode平面(BMP),碼位從U+0000至U+FFFF(除去代理區),包含了最常用的字符。UTF-16與UCS-2編碼在這個范圍內的碼位為單個16比特長的碼元,數值等價於對應的碼位。BMP中的這些碼位是僅有的碼位可以在UCS-2被表示。
2.2.3 從U+10000到U+10FFFF的碼位
輔助平面(Supplementary Planes)中的碼位,大於等於0x10000,在UTF-16中被編碼為一對16比特長的碼元(即32bit,4Bytes),稱作 code units called a 代理對(surrogate pair),具體方法是:
Ø 碼位減去0x10000, 得到的值的范圍為20比特長的0..0xFFFFF(因為Unicode的最大碼位是0x10ffff,減去0x10000后,得到的最大值是0xfffff,所以肯定可以用20個二進制位表示),寫成二進制形式:yyyy yyyy yyxx xxxx xxxx。
Ø 高位的10比特的值(值的范圍為0..0x3FF)被加上0xD800得到第一個碼元或稱作高位代理(high surrogate), 值的范圍是0xD800..0xDBFF。由於高位代理比低位代理的值要小,所以為了避免混淆使用,Unicode標准現在稱高位代理為前導代理(lead surrogates)。
Ø 低位的10比特的值(值的范圍也是0..0x3FF)被加上0xDC00得到第二個碼元或稱作低位代理(low surrogate), 現在值的范圍是0xDC00..0xDFFF。 由於低位代理比高位代理的值要大,所以為了避免混淆使用,Unicode標准現在稱低位代理為后尾代理(trail surrogates)。
Ø 最終的UTF-16(4字節)的編碼(二進制)就是:110110yyyyyyyyyy 110111xxxxxxxxxx。
按照上述規則,Unicode編碼0x10000-0x10FFFF的UTF-16編碼有兩個WORD,第一個WORD的高6位是110110,第二個WORD的高6位是110111。可見,第一個WORD的取值范圍(二進制)是11011000 00000000到11011011 11111111,即0xD800-0xDBFF。第二個WORD的取值范圍(二進制)是11011100 00000000到11011111 11111111,即0xDC00-0xDFFF。上面所說的從U+D800到U+DFFF的碼位(代理區),就是為了將一個WORD(2字節)的UTF-16編碼與兩個WORD的UTF-16編碼區分開來。
由於高位代理、低位代理、BMP中的有效字符的碼位,三者互不重疊,搜索是簡單的: 一個字符編碼的一部分不可能與另一個字符編碼的不同部分相重疊。這意味着UTF-16是自同步(self-synchronizing):可以通過僅檢查一個碼元就可以判定給定字符的下一個字符的起始碼元。 UTF-8也有類似優點,但許多早期的編碼模式就不是這樣,必須從頭開始分析文本才能確定不同字符的碼元的邊界。
由於最常有的字符都在基本多文種平面中,許多軟件的處理代理對的部分往往得不到充分的測試。這導致了一些長期的bug與潛在安全漏洞,甚至在廣為流行得到良好評價的應用軟件