Loading AI tools
統一碼編碼不同的字節倍數 来自维基百科,自由的百科全书
UTF-8(8-bit Unicode Transformation Format)是一種針對Unicode的可變長度字元編碼,也是一種字首碼。它可以用一至四個位元組對Unicode字元集中的所有有效編碼點進行編碼,屬於Unicode標準的一部分,最初由肯·湯普遜和羅布·派克提出。[2][3]由於較小值的編碼點一般使用頻率較高,直接使用Unicode編碼效率低下,大量浪費主記憶體空間。UTF-8就是為了解決向下相容ASCII碼而設計,Unicode中前128個字元,使用與ASCII碼相同的二進制值的單個位元組進行編碼,而且字面與ASCII碼的字面一一對應,這使得原來處理ASCII字元的軟體無須或只須做少部份修改,即可繼續使用。因此,它逐漸成為電子郵件、網頁及其他儲存或傳送文字優先採用的編碼方式。
此條目需要補充更多來源。 (2018年12月27日) |
此條目翻譯品質不佳。 |
自2009年以來,UTF-8一直是全球資訊網的最主要的編碼形式(對所有,而不僅是Unicode範圍內的編碼)(並由WHATWG宣布為強制性的「適用於所有事物(for all things)」,[4]截止到2019年11月, 在所有網頁中,UTF-8編碼應用率高達94.3%(其中一些僅是ASCII編碼,因為它是UTF-8的子集),而在排名最高的1000個網頁中占96%。[5] 第二熱門的多位元組編碼方式Shift JIS和GB 2312分別具有0.3%和0.2%的占有率。[6][7][1]Internet郵件聯盟( Internet Mail Consortium, IMC)建議所有電子郵件程式都能夠使用UTF-8展示和建立郵件,[8] W3C建議UTF-8作為XML檔案和HTML檔案的預設編碼方式。[9]網際網路工程工作小組(IETF)要求所有網際網路協定都必須支援UTF-8編碼[10]。網際網路郵件聯盟(IMC)建議所有電子郵件軟體都支援UTF-8編碼。[11]
1992年初,為建立良好的位元組串編碼系統以供多位元組字元集使用,開始了一個正式的研究。ISO/IEC 10646的初稿中有一個非必須的附錄,名為UTF。當中包含了一個供32位元的字元使用的位元組串編碼系統。這個編碼方式的效能並不令人滿意,但它提出了將0-127的範圍保留給ASCII以相容舊系統的概念。
1992年7月,X/Open委員會XoJIG開始尋求一個較佳的編碼系統。Unix系統實驗室(USL)的Dave Prosser為此提出了一個編碼系統的建議。它具備可更快速實作的特性,並引入一項新的改進。其中,7位元的ASCII符號只代表原來的意思,所有多位元組序列則會包含第8位元的符號,也就是所謂的最高有效位元。
1992年8月,這個建議由IBMX/Open的代表流傳到一些感興趣的團體。與此同時,貝爾實驗室九號計畫作業系統工作小組的肯·湯普遜對這編碼系統作出重大的修改,讓編碼可以自我同步,使得不必從字串的開首讀取,也能找出字元間的分界。1992年9月2日,肯·湯普遜和羅勃·派克一起在美國新澤西州一架餐車的餐桌墊上描繪出此設計的要點。接下來的日子,Pike及湯普遜將它實現,並將這編碼系統完全應用在九號計畫當中,及後他將有關成果回饋X/Open。
1993年1月25-29日的在聖地牙哥舉行的USENIX會議首次正式介紹UTF-8。
自1996年起,微軟的CAB(MS Cabinet)規格在UTF-8標準正式落實前就明確容許在任何地方使用UTF-8編碼系統。但有關的編碼器實際上從來沒有實作這方面的規格。
UTF-8使用一至六個位元組為每個字元編碼(儘管如此,2003年11月UTF-8被RFC 3629重新規範,只能使用原來Unicode定義的區域,U+0000到U+10FFFF,也就是說最多四個位元組):
對上述提及的第四種字元而言,UTF-8使用四至六個位元組來編碼似乎太耗費資源了。但UTF-8對所有常用的字元都可以用三個位元組表示,而且它的另一種選擇,UTF-16編碼,對前述的第四種字元同樣需要四個位元組來編碼,所以要決定UTF-8或UTF-16哪種編碼比較有效率,還要視所使用的字元的分佈範圍而定。不過,如果使用一些傳統的壓縮系統,比如DEFLATE,則這些不同編碼系統間的的差異就變得微不足道了。若顧及傳統壓縮演算法在壓縮較短文字上的效果不大,可以考慮使用Unicode標準壓縮格式(SCSU)。
目前有好幾份關於UTF-8詳細規格的檔案,但這些檔案在定義上有些許的不同:
它們取代了以下那些被淘汰的定義:
事實上,所有定義的基本原理都是相同的,它們之間最主要的不同是支援的字元範圍及無效輸入的處理方法。
Unicode字元的位元被分割為數個部分,並分配到UTF-8的位元組串中較低的位元的位置。在U+0080的以下字元都使用內含其字元的單位元組編碼。這些編碼正好對應7位元的ASCII字元。在其他情況,有可能需要多達4個字元組來表示一個字元。這些多位元組的最高有效位元會設定成1,以防止與7位元的ASCII字元混淆,並保持標準的位元組主導字串運作順利。
代碼範圍 十六進制 |
標量值(scalar value) 二進制 |
UTF-8 二進制/十六進制 |
註釋 |
---|---|---|---|
000000 - 00007F 128個代碼 |
00000000 00000000 0zzzzzzz | 0zzzzzzz(00-7F) | ASCII字元範圍,位元組由零開始 |
七個z | 七個z | ||
000080 - 0007FF 1920個代碼 |
00000000 00000yyy yyzzzzzz | 110yyyyy(C0-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-F7) 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個字元需要雙位元組編碼,包括帶附加符號的拉丁字母,希臘字母,西里爾字母,科普特語字母,亞美尼亞語字母,希伯來文字母和阿拉伯字母的字元。基本多文種平面中其餘的字元使用三個位元組,剩餘字元使用四個位元組。
根據這種方式可以處理更大數量的字元。原來的規範允許長達6位元組的序列,可以覆蓋到31位元(通用字元集原來的極限)。儘管如此,2003年11月UTF-8被RFC 3629重新規範,只能使用原來Unicode定義的區域,U+0000到U+10FFFF。根據這些規範,以下位元組值將無法出現在合法UTF-8序列中:
因此,對UTF-8編碼中的任意位元組,根據第一位,可判斷是否為ASCII字元;根據前二位,可判斷該位元組是否為一個字元編碼的第一個位元組;根據前四位(如果前兩位均為1),可確定該位元組為字元編碼的第一個位元組,並且可判斷對應的字元由幾個位元組表示;根據前五位(如果前四位為1),可判斷編碼是否有錯誤或資料傳輸過程中是否有錯誤。
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分1,對更長的序列的機率就更低了。
UTF-8是UNICODE的一種變長度的編碼表達方式〈一般UNICODE為雙位元組(指UCS2)〉,它由肯·湯普遜(Ken Thompson)於1992年建立,現在已經標準化為RFC 3629。UTF-8就是以8位元為單元對UCS進行編碼,而UTF-8不使用大尾序和小尾序的形式,每個使用UTF-8儲存的字元,除了第一個位元組外,其餘位元組的頭兩個位元都是以"10"開始,使文字處理器能夠較快地找出每個字元的開始位置。
但為了與以前的ASCII碼相容(ASCII為一個位元組),因此UTF-8選擇了使用可變長度位元組來儲存Unicode:
(注意:不論是Unicode (Table 3.7) [12],還是ISO 10646 (10.2 UTF-8) [13],目前都只規定了最高碼位是0x10FFFF的字元的編碼。下表中表示大於0x10FFFF的UTF-8編碼是不符合標準的。)
碼點的位數 | 碼點起值 | 碼點終值 | 位元組序列 | Byte 1 | Byte 2 | Byte 3 | Byte 4 | Byte 5 | Byte 6 |
---|---|---|---|---|---|---|---|---|---|
7 | U+0000 | U+007F | 1 | 0xxxxxxx
| |||||
11 | U+0080 | U+07FF | 2 | 110xxxxx |
10xxxxxx
| ||||
16 | U+0800 | U+FFFF | 3 | 1110xxxx |
10xxxxxx |
10xxxxxx
| |||
21 | U+10000 | U+1FFFFF | 4 | 11110xxx |
10xxxxxx |
10xxxxxx |
10xxxxxx
| ||
26 | U+200000 | U+3FFFFFF | 5 | 111110xx |
10xxxxxx |
10xxxxxx |
10xxxxxx |
10xxxxxx
| |
31 | U+4000000 | U+7FFFFFFF | 6 | 1111110x |
10xxxxxx |
10xxxxxx |
10xxxxxx |
10xxxxxx |
10xxxxxx
|
ASCII字母繼續使用1位元組儲存,重音文字、希臘字母或西里爾字母等使用2位元組來儲存,而常用的漢字就要使用3位元組。輔助平面字元則使用4位元組。
在UTF-8+BOM格式檔案的開首,很多時都放置一個U+FEFF字元(UTF-8以EF,BB,BF代表),以顯示這個文字檔案是以UTF-8編碼。
UTF-8 | |
---|---|
最小碼位 | 0000 |
最大碼位 | 10FFFF |
每位元組所占位數 | 8 bits |
Byte order | N/A |
每個字元最小位元組數 | 1 |
每個字元最大位元組數 | 4 |
總體來說,在Unicode字串中不可能由碼點數量決定顯示它所需要的長度,或者顯示字串之後在文字緩衝區中游標應該放置的位置;組合字元、變寬字型、不可列印字元和從右至左的文字都是其歸因。
所以儘管在UTF-8字串中字元數量與碼點數量的關係比UTF-32更為複雜,在實際中很少會遇到有不同的情形。
更詳細的說,UTF-8編碼具有以下幾點優點:
如果一個 UTF-8 解析器寫得很差(並且與當前標準的版本不相容),那麼它接收到一些偽 UTF-8 時會將其轉換成看似正確實則錯誤的 Unicode 輸出。處理八位表示的校驗常式可能遺漏一些資訊。
正規表示式可以進行很多進階的英文模糊檢索。例如,[a-h]表示 a 到 h 間所有字母。
同樣 GBK 編碼的中文也可以這樣利用正規表示式,比如在只知道一個字的讀音而不知道怎麼寫的情況下,也可用正規表示式檢索,因為 GBK 編碼是按讀音排序的。但是 Unicode 漢字不是按讀音排序的,所以不利於用正規表示式檢索。雖然正規表示式檢索並未考慮中文的多音字,但是由於中文的多音字數量不多,不少多音字還是同音不同調類型的多音字,所以大多數情況下正規表示式檢索是還可以接受的。不過 Unicode 漢字按部首排序,因此在只知道一個字的部首而不知道如何發音的情況下,UTF-8 可用正規表示式檢索而 GBK 不行。
由於UTF-8在編碼中可能有著空字元(null character,U+0000),這會導致C語言函示庫以及其延伸的程式解析失敗,因為這些舊有的程式庫使用這個字元來標記字串的結束。然而,之所以說「可能」,是因為這個字元是控制字元,理論上不會出現在 XML 等純文字檔案中。當萬不得已要使用空字元的時候,可能的解決方法是考慮使用 Java 的變種UTF-8 ——使用 0xc0 0x80 來編碼空字元。
UTF-8 的 ASCII 字元只占用一個位元組,比較節省空間,但是更多字元的 UTF-8 編碼佔用的空間就要多出1/2,特別是中文、日文和韓文(CJK)這樣的方塊文字,它們大多需要三個位元組。
雖然不是標準,但許多Windows程式(包括Windows記事本)在UTF-8編碼的檔案的開首加入一段位元組串EF BB BF
。這是位元組順序記號U+FEFF
的UTF-8編碼結果。對於沒有預期要處理UTF-8的文字編輯器和瀏覽器會顯示成ISO-8859-1字串
。
Posix系統明確不建議使用位元組序遮罩EF BB BF
。[14]因為很多文字檔案期望以 「#!」(Shebang)開頭指示要執行的程式。Linux系統選擇使用Unicode規範形式Normalization Form C(NFC),即優先使用預組裝字元(precomposed character)而非組合字元序列(combining character sequence)。
2002年9月發布的Red Hat Linux 8.0才開始正式把大多數區域設定的預設編碼設為UTF-8。此前是各種語言的但位元組編碼為主。2004年9月SuSE Linux 9.1開始,預設編碼遷移為UTF-8。
字串處理時,使用UTF-8或locale依賴的多位元組編碼情形,比使用C語言wchar_t的寬字元固定寬度編碼,要慢1至2個數量級。[14]
在通常用法下,Java程式語言在通過InputStreamReader
和OutputStreamWriter
讀取和寫入串的時候支援標準UTF-8。但是,Java也支援一種非標準的變體UTF-8,供對象的序列化,Java本地介面和在class檔案中的嵌入常數時使用的modified UTF-8
。
標準和變種的UTF-8有兩個不同點。第一,空字元(null character,U+0000)使用雙位元組的0xc0 0x80,而不是單位元組的0x00。這保證了在已編碼字串中沒有嵌入空位元組。因為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 (頁面存檔備份,存於網際網路檔案館)。
MySQL字元編碼集中有兩套UTF-8編碼實現:「utf8」和「utf8mb4」,其中「utf8」是一個字最多占據3位元組空間的編碼實現;而「utf8mb4」則是一個字最多占據4位元組空間的編碼實現,也就是UTF-8的完整實現。這是由於MySQL在4.1版本開始支援UTF-8編碼(當時參考UTF-8草案版本為RFC 2279)時,為2003年,並且在同年9月限制了其實現的UTF-8編碼的空間占用最多為3位元組,而UTF-8正式形成標準化文件(RFC 3629)是其之後。限制UTF-8編碼實現的編碼空間占用一般被認為是考慮到資料庫檔案設計的相容性和讀取最佳化,但實際上並沒有達到目的,而且在UTF-8編碼開始出現需要存入非基本多文種平面的Unicode字元(例如emoji字元)時導致無法存入(由於3位元組的實現只能存入基本多文種平面內的字元)。直到2010年在5.5版本推出「utf8mb4」來代替、「utf8」重新命名為「utf8mb3」並調整「utf8」為「utf8mb3」的別名,並不建議使用舊「utf8」編碼,以此修正遺留問題。[15][16][17][18]
Seamless Wikipedia browsing. On steroids.
Every time you click a link to Wikipedia, Wiktionary or Wikiquote in your browser's search results, it will show the modern Wikiwand interface.
Wikiwand extension is a five stars, simple, with minimum permission required to keep your browsing private, safe and transparent.