?? rfc2781.txt
字號:
組織:中國互動出版網(wǎng)(http://www.china-pub.com/)
RFC文檔中文翻譯計劃(http://www.china-pub.com/compters/emook/aboutemook.htm)
E-mail:ouyang@china-pub.com
譯者:huangjun(hujiao huangjun@elong.com)
譯文發(fā)布時間:2001-5-24
版權(quán):本中文翻譯文檔版權(quán)歸中國互動出版網(wǎng)所有。可以用于非商業(yè)用途自由轉(zhuǎn)載,但必須
保留本文檔的翻譯及版權(quán)信息。
Network Working Group P. Hoffman
Request for Comments: 2781 Internet Mail Consortium
Category: Informational F. Yergeau
Alis Technologies
February 2000
UTF-16, 一種ISO 10646的編碼方式
(RFC2781 UTF-16, an encoding of ISO 10646)
本備忘錄的狀態(tài)
本備忘錄描述了一種Internet社區(qū)的試驗協(xié)議。本備忘錄并未規(guī)定任何Internet標(biāo)準(zhǔn),
它需要進(jìn)一步進(jìn)行討論和建議以得到改進(jìn)。本備忘錄的發(fā)布不受限制。
版權(quán)聲明
Copyright (C) The Internet Society (2000). All Rights Reserved.
1. 介紹
本文檔描述了Unicode/ISO-10646的UTF-16編碼方式,提出了在因特網(wǎng)上將UTF-16
連續(xù)流作為八位字節(jié)流(octet stream)進(jìn)行傳輸?shù)挠^點,按照[CHARSET-REG]所描述的
MIME字符集進(jìn)行討論,還包含了MIME charset參數(shù)三個值的說明: UTF-16BE (big-endian),
UTF-16LE(little-endian)以及UTF-16。
1.1 背景和動機(jī)
Unicode標(biāo)準(zhǔn)[UNICODE]以及ISO/IEC 10646 [ISO-10646]共同定義了一整套編碼字符
(CSS),下文簡稱為Unicode,它能適應(yīng)世界上絕大多數(shù)的書寫文字[WORKSHOP]。本方
案接下來要討論的UTF-16是Unicode標(biāo)準(zhǔn)編碼方式中的一種;它的特點是,能將所有預(yù)
定義的字符(BMP中的第一組)編碼為2個字節(jié),而將其他的字符(接下來的16組)編碼為4
個字節(jié)。
Unicode標(biāo)準(zhǔn)還定義了附加的字符特性以及其他應(yīng)用者所感興趣的應(yīng)用細(xì)節(jié)。到目前為
止,對Unicode和ISO/IEC 10646的修改都是相輔相成的,這樣字符映射系統(tǒng)和代碼分配
也能夠保持同步。相關(guān)的標(biāo)準(zhǔn)化委員會承諾維持這個十分有用的同步機(jī)制,同時不會讓
UTF-16需要處理超過17組以外的字符。
在字符集和語言上的IETF政策[CHARPOLICY]表明IETF協(xié)議必須能夠使用UTF-8字
符編碼架構(gòu)[UTF-8]。一些產(chǎn)品和網(wǎng)絡(luò)標(biāo)準(zhǔn)已經(jīng)指定使用UTF-16,這使其成為Internet上一
種重要的編碼方式。本文檔并不是對[CHARPOLICY]文檔的修改更新,而僅僅描述了
UTF-16編碼方式。
1.2 專用術(shù)語
本文中所涉及的關(guān)鍵字:“必須”,“禁止”,“必需”,“應(yīng)該”,“不應(yīng)該”,“將要”,“將不
會”,“建議”,“也許”以及“可選”可參照RFC 2119 [MUSTSHOULD]中的解釋。
在本文中,字符的值用十六進(jìn)制符號表示。例如,“0x013C”表示字符在CSS中的值
為316(十進(jìn)制)。
2. UTF-16的定義
UTF-16在Unicode標(biāo)準(zhǔn)第三版[UNICODE]中被定義。定義的有關(guān)參考文獻(xiàn)可參看
ISO/IEC 10646-1 [ISO-10646]附錄Q。本節(jié)后面將簡單概括該定義。
在ISO 10646中,每個字符被分配一個數(shù)字,Unicode將其稱為Unicode值,這個數(shù)
字和UCS-4中字符的值一樣,為簡單起見,本文將該數(shù)字稱為“字符的值”。在UTF-16編
碼中,字符根據(jù)其本身的值,用一個或兩個無符號的16位整數(shù)來表示,將這些整數(shù)線性化
以便作為字節(jié)流進(jìn)行傳輸將在第3部分加以討論。
字符按照UTF-16進(jìn)行編碼的規(guī)則是:
- 字符的值小于0x10000的用等于該值的16位整數(shù)來表示。
- 字符的值介于0x10000和0x10FFFF之間的,用一個值介于0xD800和0xDBFF(在
所謂的高8位區(qū))的16位整數(shù)和值介于0xDC00和0xDFFF(在所謂的低8位區(qū))的16位整
數(shù)來表示。
- 字符的值大于0x10FFFF不能按照UTF-16進(jìn)行編碼。
注意:在0xD800和0xDFFF間的值是特別為UTF-16預(yù)留,所以不應(yīng)該將任何字符的值指
定為這個區(qū)間內(nèi)的數(shù)值。
2.1 UTF-16編碼
將某個字符的ISO 10646的值轉(zhuǎn)換為UTF-16的編碼按照以下步驟進(jìn)行。假設(shè)U是給
字符的值,小于0x10FFFF。
1) 如果U < 0x10000,U的編碼就是無符號的十六位整數(shù),值和其本身的值一樣,處理結(jié)
束。
2) 如果U等于或者小于0x10FFFF,則設(shè)U' = U - 0x10000。此時,U'一定小于或者等于
0xFFFFF,也就是說,U'的值不會超過20位。
3) 分別初始化2個16位無符號的整數(shù),W1和W2為0xD800和0xDC00。每個整數(shù)都有
10位可以用來對字符進(jìn)行編碼,正好能容納U'的20位。
4) 將U'的高10位分配給W1的低10位,將U'的低10位分配給W2的低10位,處理結(jié)
束。
用數(shù)字來表示,第2步到第4步如下所示:
U' = yyyyyyyyyyxxxxxxxxxx
W1 = 110110yyyyyyyyyy
W2 = 110111xxxxxxxxxx
2.2 UTF-16解碼
將單個字符從UTF-16解碼為ISO 10646值的步驟如下。設(shè)W1為待解碼文字中第一個
16位的整數(shù),設(shè)W2為跟在W1后的整數(shù)(如果有的話)。
1) 如果W1小于0xD800或者W1大于0xDFFF,字符的值U就是W1的值,處理結(jié)束。
2) 判斷W1的值是否介于0xD800和0xDBFF之間。如果不是,那么順序有誤,而且用
W1將不能解碼出任何合法字符。處理結(jié)束。
3) 如果沒有W2(也就是說,以W1結(jié)尾),或者雖然有W2,但不是介于0xDC00和0xDFFF
之間,那么順序同樣有錯。處理結(jié)束。
4) 建立一個20位的無符號整數(shù)U',將W1的低10位作為U'的高10位,將W2的低10位
作為U'的低10位。
5) 將U'的值加上0x10000以得到字符U的值,處理結(jié)束。
需要注意的是步驟2和步驟3指出了錯誤。本文檔并沒有討論有關(guān)錯誤恢復(fù)機(jī)制。當(dāng)在
步驟2和步驟3中發(fā)生錯誤而導(dǎo)致處理中斷的時候,將U的值設(shè)為W1的值可能是比較明
智的做法,這樣有助于調(diào)用者診斷該錯誤,同時也不會丟失信息。另外還要注意的是字符串
解碼算法和上文所描述的單個字符解碼方法略有不同,如果有適當(dāng)?shù)腻e誤報告或者是錯誤恢
復(fù)機(jī)制的話,發(fā)生錯誤時將不應(yīng)該中斷后續(xù)的解碼操作。
3. 標(biāo)識UTF-16文字
本方案的附錄A包含了MIME字符集的三個注冊說明:"UTF-16BE", "UTF-16LE", 以
及"UTF-16"。MIME字符集表示CCS(編碼字符集)和CES(字符編碼方案)的結(jié)合。這里所說
的CCS是Unicdoe/ISO 10646,而CES在三種情況下都是一致的,除了每個字符線性字
節(jié)流的順序不同,同時也是外部判別采用那種線性化方法的一種手段。
本節(jié)將討論對一個文本流應(yīng)該采用三種標(biāo)識中的哪一種。第4節(jié)將描述如何解釋文本流
的標(biāo)識。
3.1 big-endian和little-endian的定義
就過去而言,計算機(jī)有兩種方法來處理類似16位整數(shù)這樣的雙八位字節(jié)數(shù)。所謂的
"big-endian"硬件處理雙八位字節(jié)時先處理位于內(nèi)存中低地址的高位字節(jié)。當(dāng)將其輸出到磁
盤或者到網(wǎng)絡(luò)接口的時候(線性化),高位字節(jié)也就先出現(xiàn)在數(shù)據(jù)流中。而與此相對應(yīng)的是,
"Little-endian"硬件先處理低位字節(jié)。目前來說,兩種硬件都很常見。
舉例來說,代表十進(jìn)制258的無符號16位整數(shù)是0x0102。big-endian將其線性化輸出
為八位字節(jié)0x01,后面跟著0x02。而little-endian將其線性化輸出為八位字節(jié)0x02,后面
跟著0x01。接下來的C代碼片段就演示了如何將16位數(shù)按照big-endian順序?qū)懭氲轿募?中,而不考慮硬件本身的字節(jié)順序。
void write_be(unsigned short u, FILE f) /* 假設(shè)short 為16位 */
{
putc(u >> 8, f); /* 輸出高字節(jié) */
putc(u & 0xFF, f); /* 然后輸出低字節(jié) */
}
雖然術(shù)語“網(wǎng)絡(luò)字節(jié)順序(network byte order)”并沒有正式在標(biāo)準(zhǔn)文檔中作出有關(guān)定義,
但在許多RFC中該詞語都被用來表明big-endian線性化過程。盡管ISO 10646采用
big-endian線性化([ISO-10646]6.3節(jié)),但是在因特網(wǎng)上有時候仍然使用little-endian順序。
3.2 字節(jié)順序標(biāo)志(BOM)
Unicode標(biāo)準(zhǔn)和ISO 10646將0xFEFF定義為字符“零寬度不換行的空格”,同時一般
也認(rèn)同為“字節(jié)順序標(biāo)準(zhǔn)(簡稱為BOM)”。后者暗示了該字符除了通常的在文本中作為“零
寬度不換行的空格”使用外,還有另一種可能的用處。根據(jù)Unicode第2.4節(jié)和ISO 10646
附錄F(完整版)所建議的,將0xFEFF字符作為Unicode字節(jié)流中的一個“簽名”;當(dāng)接收
方收到一個字節(jié)流的時候,借助這個首字節(jié),既可以確定該字節(jié)流包含了Unicode字符,
也可以用來辨認(rèn)線性化的順序。在帶有該簽名的線性化UTF-16流中,如果開始的兩個八位
字節(jié)為0xFE后面跟著0xFF的話,線性化順序就是big-endian;如果為0xFF后面跟著0xFE,
線性化順序就是little-endian。注意0xFFFE并不是一個Unicode字符,所以正好用它來作
為字節(jié)順序的標(biāo)志。
很重要的一點就是,如果字符0xFEFF在字節(jié)流中的其他地方而不是首字節(jié)出現(xiàn)的話,
它就必須被解釋為“零寬度不換行的空格”。但這句話的反義并不總是正確的:在字節(jié)流首
位出現(xiàn)的字符0xFEFF可能被解釋為“零寬度不換行的空格”,而不一定總是字節(jié)順序標(biāo)志。
舉例來說,如果一個處理將一個UTF-16字符串分隔為許多個部分,那么其中某個部分的子
串正好是以零寬度不換行的空格開頭的話,就可能以0xFEFF開頭。
此外,Unicode標(biāo)準(zhǔn)還建議在開始處理文本前,應(yīng)該將開頭的0xFEFF字符去掉,這樣
建議的原理是因為在開始位置的這個字符可能是人為添加的編碼(一個編碼的簽名),而不
是真正意義上的“零寬度不換行的空格”。需要注意的是這樣做可能會影響在另外一個不同
層中需要依靠流中所有字符進(jìn)行處理的外部處理過程(比如說一個數(shù)字簽名或?qū)ψ址挠?數(shù))。
特別地,雖然有例外情況,但在UTF-16純文本中,以0xFEFF開始的字符非常可能是
一個簽名。當(dāng)連接兩個字符串的時候,將這些簽名去掉就顯得非常重要了,否則生成的字串
中的連接點上就可能包含本來沒有的“零寬度不換行的空格”。此外,有一些規(guī)范要求那些
標(biāo)明為UTF-16的對象必須在開始位置保留0xFEFF字符,同時注明該簽名并不是對象本身
的組成部分。
3.3 為UTF-16文字選擇標(biāo)識
任何使用UTF-16文字編碼的標(biāo)識程序,在明確地標(biāo)識文字的時候,如果知道字符的線
性化順序,必須根據(jù)文字本身的字節(jié)順序,將文字標(biāo)明為"UTF-16BE"或者"UTF-16LE"。這
能讓那些處理文字的應(yīng)用程序不用研究文字本身就可以確切地知道線性化的順序。
在"UTF-16BE"字符中的文字必須按照big-endian的順序組裝UTF-16的16位字符值,
系統(tǒng)在標(biāo)識UTF-16BE文字的時候,不應(yīng)該給文字加上BOM(字節(jié)順序標(biāo)準(zhǔn))。
在"UTF-16LE"字符中的文字必須按照little-endian的順序組裝UTF-16的16位字符值,
系統(tǒng)在標(biāo)識UTF-16LE文字的時候,不應(yīng)該給文字加上BOM(字節(jié)順序標(biāo)準(zhǔn))。
任何使用UTF-16文字編碼的標(biāo)識程序,在給文字加上明確的字符集標(biāo)簽的時候,如果
不知道文字中字符的線性化順序,必須將文字標(biāo)識為"UTF-16",同時應(yīng)該讓文字以0xFEFF
開頭。
在必須使用"UTF-16BE"或者"UTF-16LE"的一個例外情況就是,如果文檔格式中要求為
UTF-16文字提供BOM的話,那就只需要將其標(biāo)識為"UTF-16"。
4. 解釋文字標(biāo)識
當(dāng)一個程序發(fā)現(xiàn)文字被標(biāo)識為"UTF-16BE", "UTF-16LE"或者"UTF-16"的時候,它將能
夠根據(jù)我們前文所提到的標(biāo)識規(guī)則作出一些假定。這些假定將有助于程序接下來如何對文字
進(jìn)行處理。
4.1 解釋標(biāo)識為UTF-16BE的文本
標(biāo)識為UTF-16BE的文本可以被解釋為采用big-endian順序。即使首字節(jié)有BOM存在
也不會影響標(biāo)識為UTF-16BE的文本的反線性化過程。如果發(fā)現(xiàn)0xFF后面跟著0xFE,將
意味著發(fā)生了錯誤,因為沒有0xFFFE的Unicode字符。
4.2 解釋標(biāo)識為UTF-16LE的文本
標(biāo)識為UTF-16LE的文本可以被解釋為采用little-endian順序。即使首字節(jié)有BOM存
在也不會影響標(biāo)識為UTF-16LE的文本的反線性化過程。在按照little-endian順序解釋這些
字節(jié)的時候,如果發(fā)現(xiàn)0xFE后面跟著0xFF,將意味著發(fā)生了錯誤,因為沒有0xFFFE的
Unicode字符。
4.3 解釋標(biāo)識為UTF-16的文本
標(biāo)識為"UTF-16"的字符集可能是按照big-endian的順序,也可能是按照little-endian順
序進(jìn)行線性化的。如果開始的兩個字節(jié)是0xFE后面跟著0xFF,那么文字可以被解釋為使
用big-endian順序。反之,如果開始的兩個字節(jié)是0xFF后面跟著0xFE,那么文字是采用
了little-endian順序。如果開始的兩個字節(jié)不是0xFE,0xFF,而同時也不是0xFF后面跟
著0xFE的話,那么文字就應(yīng)該被解釋為使用big-endian順序。
所有處理標(biāo)識為UTF-16的文字的應(yīng)用程序,都必須能讀文字開始部分的最少兩個字節(jié),
并且能處理這些字節(jié)以確定文字的線性化方向。處理標(biāo)識為UTF-16的文字的應(yīng)用程序禁止
在沒有檢查開始的兩位字節(jié),并判斷是big-endian BOM還是little-endian BOM,或者不是
BOM的情況下就假定線性化方向。所有處理標(biāo)識為UTF-16的文字的應(yīng)用程序必須既能夠
解釋big-endian文字,也能夠解釋little-endian文字。
5. 示例
舉例來說,讓我們假定有一個字符代表埃及語中描寫神Ra的象形文字,它的值是
0x12345。(這個字符在現(xiàn)有的Unicode中并不存在)。
在示例中所有的詞組中:
*=Ra
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -