| 此條目可能需要進行清理,以符合維基百科的品質標準。(2007年12月31日) 請儘量協助改善這篇條目,詳細信息請參見討論頁。 |
UTF-8(8 位元 Universal Character Set/Unicode Transformation Format)是針對Unicode 的一種可變長度字元編碼。它可以用來表示 Unicode 標準中的任何字元,而且其編碼中的第一個位元組仍與 ASCII 相容,使得原來處理 ASCII 字元的軟體無需或只作少部份修改後,便可繼續使用。因此,它逐漸成為電子郵件、網頁及其他儲存或傳送文字的應用中,優先採用的編碼。
UTF-8 使用一至四個位元組為每個字元編碼:
對上述提及的第四種字元而言,UTF-8 使用四個位元組來編碼似乎太耗費資源了。但 UTF-8 對所有常用的字元都可以用三個位元組表示,而且它的另一種選擇,UTF-16編碼,對前述的第四種字元同樣需要四個位元組來編碼,所以要決定 UTF-8 或 UTF-16 哪種編碼比較有效率,還要視所使用的字元的分佈範圍而定。不過,如果使用一些傳統的壓縮系統,比如 DEFLATE,則這些不同編碼系統間的的差異就變得微不足道了。若顧及傳統壓縮演算法在壓縮較短文字上的效果不大,可以考慮使用 Standard Compression Scheme for Unicode(SCSU)。
網際網路工程工作小組(IETF)要求所有網際網路協議都必須支援 UTF-8 編碼。[1] 網際網路郵件聯盟(IMC)建議所有電子郵件軟體都支援 UTF-8編碼。所有主要的電子郵件軟體中,只有 Eudora 不支援 UTF-8 編碼。[1]
目錄 |
1992年初,為建立良好的位元組串編碼系統(byte-stream encoding)以供多位元組字元集(multi-byte character sets)使用,開始了一個正式的研究。ISO/IEC 10646的初稿中有一個非必須的附錄,名為UTF。當中包含了一個供32位元的字元使用的位元組串編碼系統。這個編碼方式的性能並不令人滿意,但它提出了將0-127的範圍保留給ASCII以相容舊系統的概念。
1992年7月,X/Open委員會XoJIG開始尋求一個較佳的編碼系統。UNIX 系統實驗室(UNIX System Laboratories, USL)的Dave Prosser為此提出了一個編碼系統的建議。它具備可更快速實作的特性,並引入一項新的改進。其中,7位元的ASCII符號只代表原來的意思,所有多位元組序列則會包含第8位元的符號,也就是所謂的最高有效位元。
1992年8月,這個建議由IBMX/Open的代表流傳到一些感興趣的團體。與此同時,貝爾實驗室Plan 9作業系統工作小組的肯·湯普遜對這編碼系統作出重大的修改,讓編碼可以自我同步(self-synchronizing),使得不必從字串的開首讀取,也能找出字元間的分界。1992年9月2日,湯普遜和Pike一起在美國新澤西州一架餐車的餐桌墊上描繪出此設計的要點。接下來的日子,Pike及湯普遜將它實現,並將這編碼系統完全應用在Plan 9當中,及後他將有關成果回饋X/Open。
1993年1月25-29日的在聖地牙哥舉行的USENIX會議首次正式介紹UTF-8。
自1996年起,微軟的CAB(MS Cabinet)規格在UTF-8標準正式落實前就明確容許在任何地方使用UTF-8編碼系統。但有關的編碼器實際上從來沒有實作這方面的規格。
目前有好幾份關於UTF-8詳細規格的文件,但這些文件在定義上有些許的不同:
它們取代了以下那些被淘汰的定義:
事實上,所有定義的基本原理都是相同的,它們之間最主要的不同是支援的字元範圍及無效輸入的處理方法。
Unicode字元的位元被分割為數個部分,並分配到UTF-8的位元組串中較低的位元的位置。在U+0080的以下字元都使用內含其字元的單位元組編碼。這些編碼正好對應7位元的ASCII字元。在其他情況,有可能需要多達4個字元組來表示一個字元。這些多位元組的最高有效位元會設定成1,以防止與7位元的ASCII字元混淆,並保持標準的位元組主導字串(standard byte-oriented string)運作順利。
| 代碼範圍 十六進制 |
標量值(scalar value) 二進制 |
UTF-8 二進制 / 十六進制 |
註釋 |
|---|---|---|---|
| 000000 - 00007F 128個代碼 |
00000000 00000000 0zzzzzzz | 0zzzzzzz(00-7F) | ASCII字元範圍,位元組由零開始 |
| 七個z | 七個z | ||
| 000080 - 0007FF 1920個代碼 |
00000000 00000yyy yyzzzzzz | 110yyyyy(C2-DF) 10zzzzzz(80-BF) | 第一個位元組由110開始,接著的位元組由10開始 |
| 三個y;二個y;六個z | 五個y;六個z | ||
| 000800 - 00D7FF 00E000 - 00FFFF 61440個代碼 [Note 1] |
00000000 xxxxyyyy yyzzzzzz | 1110xxxx(E0-EF) 10yyyyyy 10zzzzzz | 第一個位元組由1110開始,接著的位元組由10開始 |
| 四個x;四個y;二個y;六個z | 四個x;六個y;六個z | ||
| 010000 - 10FFFF 1048576個代碼 |
000wwwxx xxxxyyyy yyzzzzzz | 11110www(F0-F4) 10xxxxxx 10yyyyyy 10zzzzzz | 由11110開始,接著的位元組由10開始 |
| 三個w;二個x;四個x;四個y;二個y;六個z | 三個w;六個x;六個y;六個z |
例如,希伯來語字母 aleph (א)的Unicode代碼是 U+05D0,按照以下方法改成 UTF-8:
所以開始的128個字元(US-ASCII)只需一位元組,接下來的1920個字元需要雙位元組編碼,包括帶變音符號的拉丁字母, 希腊字母, 西里爾字母, 科普特語字母, 亞美尼亞語字母, 希伯來文字母和阿拉伯字母的字元。BMP其餘的字元使用三個位元組,剩餘字元使用四個位元組。
根據這種方式可以處理更大數量的字元。原來的規範允許長達6位元組的序列,可以覆蓋到31位元 (通用字元集原來的極限)。儘管如此,2003年11月UTF-8 被 RFC 3629 重新規範,只能使用原來Unicode定義的區域, U+0000到U+10FFFF。根據這些規範,以下位元組值將無法出現在合法 UTF-8序列中:
| 編碼(二進位) | 編碼(十六進位) | 註釋 |
|---|---|---|
| 1100000x | C0, C1 | 過長編碼:雙位元組序列的頭位元組,但碼點<= 127 |
| 1111111x | FE, FF | 無法達到: 7 或8位元組序列的頭位元組 |
| 111110xx 1111110x |
F8, F9, FA, FB, FC, FD | 被RFC 3629規範: 5 或 6位元組序列的頭位元組 |
| 11110101 1111011x |
F5, F6, F7 | 被RFC 3629規範: 碼點超過10FFFF的頭位元組 |
雖然至少有兩類在技術上是受以前的 UTF-8規範所支援,但這些編碼上還沒有被賦予字元,所以不會在實際的文本中出現。 演算法設計與霍夫曼編碼類似。
雖然不是標準,但許多Windows 程序(包括Windows 筆記本) 在UTF-8編碼的檔案的開首加入一段位元組串EF BB BF。這是編碼成UTF-8的Byte Order Mark U+FEFF。沒有預期要處理UTF-8的文字編輯器和瀏覽器會會顯示為ISO-8859-1字元""。
在通常用法下,Java程序語言在通過Template:Javadoc:SE 和Template:Javadoc:SE讀取和寫入串的時候支持標準UTF-8。但是,Java也支持一種非標準的變體UTF-8,供對象的系列化,Java本地界面和在class文件中的嵌入常數時使用的Template:Javadoc:SE。
標準和改正的UTF-8有兩個不同點。第一,空字元 (null character,U+0000)使用雙位元組,而不是單位元組,分別是11000000 10000000。這保證了在已編碼字串中沒有嵌入空位元組。因為C語言等語言程序中,單位元組空字元是用來標誌串串結尾的。當已編碼字串放到這樣的語言中處理,一個嵌入的空字元將把字串一刀兩斷。
第二個不同點是基本多文種平面之外字元的編碼的方法。在標準UTF-8中,這些字元使用4位元組形式編碼,而在改正的UTF-8中,這些字元和UTF-16一樣首先表示為代理對(surrogate pairs),然後再像CESU-8那樣按照代理對分別編碼。這樣改正的原因更是微妙。Java中的字元為16位長,因此一些Unicode字元需要兩個Java字元來表示。語言的這個性質蓋過了Unicode的增補平面的要求。儘管如此,為了要保持良好的向後兼容、要改變也不容易了。這個改正的編碼系統保證了一個已編碼字串可以一次編為一個UTF-16碼,而不是一次一個Unicode碼點。 不幸的是,這也意味著UTF-8中需要4位元組的字元在改正UTF-8中變成需要6位元組。
因為改正的UTF-8並不是 UTF-8,所以用戶在交換信息和使用互聯網的時候需要特別註意不要誤把改正UTF-8當成UTF-8數據。
Mac OS X操作系統使用正式分解萬國碼(canonically decomposed Unicode),在文件系統中使用UTF-8編碼進行文件命名,這做法通常被稱為UTF-8-MAC。正式分解萬國碼中,預分解字元是被禁止使用的,必須以組合字元取代。
這種方法使分類變得非常簡單,但是會搞混那些使用預分解字元為標準、組合字元用來顯示特殊字元的軟體。Mac系統的這種NFD數據是萬國碼規範化(Unicode normalization)的一種格式。而其他系統, 包括Windows和 Linux, 使用萬國碼規範的NFC形式,也是W3C標準使用的形式。所以NFD數據必須典型的轉換成NFC才能被其他平臺或者網路使用。
在此有關於此問題的討論 Apple Q&A 1173.
UTF-8的設計有以下的多字元組序列的特質:
110的是2位元組序列,而1110的是三位元組序列,如此類推。10。UTF-8的這些特質,保證了一個字元的位元組序列不會包含在另一個字元的位元組序列中。這確保了以位元組為基礎的部份字串比對(sub-string match)方法可以適用於在文字中搜尋字或詞。有些比較舊的可變長度8位元編碼(如Shift-JIS)沒有這個特質,故字串比對的演算法變得相當複雜。雖然這增加了UTF-8編碼的字串的冗餘,但是利多於弊。另外,資料壓縮並非Unicode 的目的,所以不可混為一談。即使在傳送過程中有部份位元組因錯誤或乾擾而完全遺失,還是有可能在下一個字元的起點重新同步,令受損範圍受到限制。
另一方面,由於其位元組序列設計,如果一個疑似為字元串的序列被驗證為UTF-8編碼,那麼我們可以有把握地說它是UTF-8字元串。一段兩位元組隨機序列碰巧為合法的UTF-8而非ASCII 的機率為32分1。對於三位元組序列的機率為256分3,對更長的序列的機率就更低了。
關於字元串長度的一個註解:
總體來說,在Unicode字元串中不可能由碼點數量決定顯示它所需要的長度,或者顯示字元串之後在文本緩衝區中游標應該放置的位置;組合字元、變寬字體、不可列印字元和從右至左的文字都是其歸因。
所以儘管在UTF-8字元串中字元數量與碼點數量的關係比UTF-32更為複雜,在實際中很少會遇到有不同的情形。
ASCII轉換成UCS-2,在編碼前插入一個0x0。用這些編碼,會含括一些控制符,比如 " 或 '/',這在UNIX和一些C函數中,將會産生嚴重錯誤。因此可以肯定,UCS-2不適合作為Unicode的外部編碼,也因此誕生了UTF-8。
UTF-8是UNICODE的一種變長度的編碼表達方式 〈一般UNICODE為雙位元組(指UCS2)〉,它由Ken Thompson於1992年建立,現在已經標準化為RFC 3629。UTF-8就是以8位為單元對UCS進行編碼,而UTF-8不使用大尾序和小尾序的形式,每個使用UTF-8儲存的字元,除了第一個位元組外,其餘位元組的頭兩個位元都是以 "10" 開始,使文字處理器能夠較快地找出每個字元的開始位置。
但為了與以前的ASCII碼相容 (ASCII為一個位元組),因此 UTF-8 選擇了使用可變長度位元組來儲存 Unicode:
| UCS-2編碼 | UTF-8位元組流 |
|---|---|
| U-00000000 – U-0000007F: | 0xxxxxxx |
| U-00000080 – U-000007FF: | 110xxxxx 10xxxxxx |
| U-00000800 – U-0000FFFF: | 1110xxxx 10xxxxxx 10xxxxxx |
| U-00010000 – U-001FFFFF: | 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx |
| U-00200000 – U-03FFFFFF: | 111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx |
| U-04000000 – U-7FFFFFFF: | 1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx |
ASCII字母繼續使用1位元組儲存,重音文字、希臘字母或西里爾字母等使用2位元組來儲存,而常用的漢字就要使用3位元組。輔助平面字元則使用4位元組。
在UTF-8文件的開首,很多時都放置一個U+FEFF字元 (UTF-8 以 EF,BB,BF 代表),以顯示這個文字檔案是以UTF-8編碼。
| UTF-8 | |
|---|---|
| Smallest code point | 0000 |
| Largest code point | 10FFFF |
| Code unit size | 8 bits |
| Byte order | N/A |
| Minimal bytes/character | 1 |
| Maximal bytes/character | 4 |
【註】
正則表達式可以進行很多英文高級的模糊檢索。例如,[a-h]表示a到h間所有字母。
同樣GBK編碼的中文也可以這樣利用正則表達式,比如在只知道一個字的讀音而不知道怎麼寫的情況下,也可用正則表達式檢索,因為GBK編碼是按讀音排序的。只是UTF-8不是按讀音排序的,所以會對正則表達式檢索造成不利影響。但是這種使用方式並未考慮中文中的破音字,因此影響不大。Unicode是按部首排序的,因此在只知道一個字的部首而不知道如何發音的情況下,UTF-8 可用正則表達式檢索而GBK不行。
與其他 Unicode 編碼相比,特別是UTF-16,在 UTF-8 中 ASCII 字元佔用的空間只有一半,可是在一些字元的 UTF-8 編碼佔用的空間就要多出,特別是中文、日文和韓文(CJK)這樣的象形文字,所以具體因素因文檔而異,但不論哪種情況,差別都不可能很明顯。
| Unicode 相關的條目 |
|---|
| Unicode字元列表 | Unicode聯盟 | Unicode技術委員會 | ISO 10646 (通用字元集) | UTF-7 | UTF-8 | UTF-16 / UCS-2 | UTF-32 / UCS-4 |
| 基本多文種平面 | 輔助平面 | 中日韓統一表意文字 | CJKV | 表意文字小組 (IRG) | IICore | 完整Unicode編碼表 |
Why are we here?
All text is available under the terms of the GNU Free Documentation License
This page is cache of Wikipedia. History