簡介
什麼是UTF-8
UTF,是 Unicode Transformation Format的縮寫,意為Unicode轉換格式。
如果UNICODE字元由2個位元組表示,則編碼成UTF-8很可能需要3個位元組,而如果UNICODE字元由4個位元組表示,則編碼成UTF-8可能需要6個位元組。用4個或6個位元組去編碼一個UNICODE字元可能太多了,但很少會遇到那樣的UNICODE字元。
簡史
ASCII碼
在所有字元集中,最知名可能要數被稱為ASCⅡ的7位字元集了。它是美國信息交換標準委員會(American Standard Code for Information Interchange)的縮寫,為美國英語通信所設計。它由128個字元組成,包括大小寫字母、數字0-9、標點符號、非列印字元(換行符、制表符等4個)以及控制字元(退格、響鈴等)組成。標準的ASCII碼用一個位元組存儲,可以表示128個字元,其中最高位用作校驗碼。
擴展碼
但是,由於他是針對英語設計的,當處理帶有音調標號(形如漢語的拼音)的歐洲文字時就會出現問題。為了表示更多字元,人們打起了校驗碼的注意,讓最高位也用作字元表示,這就是ASCII碼擴字元集。ASCII擴展的字元集包括255個字元。其中有一種通常被稱為IBM字元集,它把值為128-255之間的字元用於畫圖和畫線,以及一些特殊的歐洲字元。另一種8位字元集是ISO 8859-1Latin 1,也簡稱為ISO Latin-1。它把位於128-255之間的字元用於拉丁字母表中特殊語言字元的編碼,也因此而得名。
編碼
歐洲語言不是地球上的唯一語言,因此亞洲和非洲語言並不能被8位字元集所支持。僅漢語(或pictograms)字母表就有80000以上個字元。但是把漢語、日語和越南語的一些相似的字元結合起來,在不同的語言裡,使不同的字元代表不同的字,這樣只用2個位元組就可以編碼地球上幾乎所有地區的文字。因此,創建了UNICODE編碼。它通過增加一個高位元組對ISO Latin-1字元集進行擴展,當這些高位元組位為0時,低位元組就是ISO Latin-1字元。UNICODE支持歐洲、非洲、中東、亞洲(包括統一標準的東亞像形漢字和韓國像形文字)。但是,UNICODE並沒有提供對諸如Braille,Cherokee,Ethiopic,Khmer,Mongolian,Hmong,Tai Lu,Tai Mau文字的支持。同時它也不支持如Ahom,Akkadian,Aramaic,Babylonian Cuneiform,Balti,Brahmi,Etruscan,Hittite,Javanese,Numidian,Old Persian Cuneiform,Syrian之類的古老的文字。
轉換格式
事實證明,對可以用ASCII表示的字元使用UNICODE並不高效,因為UNICODE比ASCII占用大一倍的空間,而對ASCII來說高位元組的0對他毫無用處。為了解決這個問題,就出現了一些中間格式的字元集,他們被稱為通用轉換格式,即UTF(Unicode Transformation Format)。目前存在的UTF格式有:UTF-7,UTF-7.5,UTF-8,UTF-16,以及 UTF-32。本文討論UTF-8字元集的基礎。
IE亂碼
UNICODE(UTF-8)這個項目放在 IE 的選單欄下是為了讓你能夠強制 IE 用 UTF-8字元集顯示頁面。
只有在頁面編碼為 UTF-8 但 IE 卻無法正確地選擇 UTF-8字元集來顯示頁面的時候,你才應該動用該項目。
如果你選擇該項目,這個頁面將被顯示成亂碼,因為這個頁面的編碼是 GB2312 (簡體中文),不是 UTF-8。以不正確的編碼顯示頁面就好像把漢語拼音當成法語來念,結果當然是沒人能聽懂的亂語。
首先 UCS 和 Unicode 只是分配整數給字元的編碼表. 現在存在好幾種將一串字元表示為一串位元組的方法. 最顯而易見的兩種方法是將 Unicode 文本存儲為 2 個 或 4 個位元組序列的串. 這兩種方法的正式名稱分別為 UCS-2 和 UCS-4. 除非另外指定,否則大多數的位元組都是這樣的(Bigendian convention). 將一個 ASCII 或 Latin-1 的檔案轉換成 UCS-2 只需簡單地在每個 ASCII 位元組前插入 0x00. 如果要轉換成 UCS-4,則必須在每個 ASCII位元組前插入三個 0x00.
在 Unix 下使用 UCS-2 (或 UCS-4) 會導致非常嚴重的問題. 用這些編碼的字元串會包含一些特殊的字元,比如 '\0' 或 '/',它們在 檔案名稱和其他 C庫函式參數裡都有特別的含義. 另外,大多數使用 ASCII 檔案的 UNIX 下的工具,如果不進行重大修改是無法讀取 16 位的字元的. 基於這些原因,在檔案名稱,文本檔案,環境變數等地方,UCS-2 不適合作為 Unicode 的外部編碼.
在 ISO 10646-1 Annex R 和 RFC 2279 里定義的 UTF-8 編碼沒有這些問題. 它是在 Unix 風格的作業系統下使用 Unicode 的明顯的方法.
特性
UCS 字元 U+0000 到 U+007F (ASCII) 被編碼為位元組0x00 到 0x7F (ASCII 兼容). 這意味著只包含 7 位 ASCII 字元的檔案在 ASCII 和 UTF-8 兩種編碼方式下是一樣的.
所有 >U+007F 的 UCS字元被編碼為一個多個位元組的串,每個位元組都有標記位集. 因此,ASCⅡ 位元組 (0x00-0x7F) 不可能作為任何其他字元的一部分.
表示非 ASCⅡ字元的多位元組串的第一個位元組總是在 0xC0 到 0xFD 的範圍里,並指出這個字元包含多少個位元組. 多位元組串的其餘位元組都在 0x80 到 0xBF 範圍里. 這使得重新同步非常容易,並使編碼無國界,且很少受丟失位元組的影響.
可以編入所有可能的 231個 UCS 代碼
UTF-8 編碼字元理論上可以最多到 6 個位元組長,然而 16 位 BMP 字元最多只用到 3 位元組長.
Bigendian UCS-4位元組串的排列順序是預定的.
位元組0xFE 和 0xFF 在 UTF-8 編碼中從未用到.
下列位元組串用來表示一個字元. 用到哪個串取決於該字元在 Unicode 中的序號.
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
xxx 的位置由字元編碼數的二進制表示的位填入, 越靠右的 x 具有越少的特殊意義,只用最短的那個足夠表達一個字元編碼數的多位元組串, 注意在多位元組串中,第一個位元組的開頭"1"的數目就是整個串中位元組的數目。
例如: Unicode字元U+00A9 = 1010 1001 (著作權符號) 在 UTF-8 里的編碼為:
11****1*1*1*1**1=0xC20xA9【註:*號代表0】
而字元U+2260 = **1* **1* * 11* **** 【註:*號代表0】(不等於) 編碼為:
111****1* 1*** 1***1 1* 1***** = 0xE2 0x89 0xA0
這種編碼的官方名字拼寫為 UTF-8,其中 UTF 代表 UCS Transformation Format. 請勿在任何文檔中用其他名字 (比如 utf8 或 UTF_8) 來表示 UTF-8,當然除非你指的是一個變數名而不是這種編碼本身.
優點
UTF-8編碼可以通過禁止位和移位操作快速讀寫。字元串比較時strcmp()和wcscmp()的返回結果相同,因此使排序變得更加容易。位元組FF和FE在UTF-8編碼中永遠不會出現,因此他們可以用來表明UTF-16或UTF-32文本(見BOM) UTF-8 是位元組順序無關的。它的位元組順序在所有系統中都是一樣的,因此它實際上並不需要BOM。
缺點
你無法從UNICODE字元數判斷出UTF-8文本的位元組數,因為UTF-8是一種變長編碼它需要用2個位元組編碼那些用擴展ASCⅡ字元集只需1個位元組的字元 ISO Latin-1 是UNICODE的子集,但不是UTF-8的子集 8位字元的UTF-8編碼會被email網關過濾,因為internet信息最初設計為7位ASCⅡ碼。因此產生了UTF-7編碼。UTF-8 在它的表示中使用值100xxxxx的幾率超過50%, 而現存的實現如ISO 2022, 4873, 6429, 和8859系統,會把它錯認為是C1 控制碼。因此產生了UTF-7.5編碼。
關於utf-8
java使用UTF-16表示內部文本,並支持用於字元串串列化的非標準的修正UTF-8編碼。標準UTF-8和修正的UTF-8有兩點不同:修正的UTF-8中,null字元編碼成2個位元組(11****** 1*******)【註:*號代表0】 而不是標準的1個位元組(00000000),這樣作可以保證編碼後的字元串中不會嵌入null字元。因此如果在類C語言中處理字元串,文本不會在第一個null字元時截斷(C字元串以null結尾)。在標準UTF-8編碼中,超出基本多語言範圍(BMP - Basic Multilingual Plain)的字元被編碼為4位元組格式,但是在修正的UTF-8編碼中,他們由代理編碼對(surrogate pairs)表示,然後這些代理編碼對在序列中分別重新編碼。結果標準UTF-8編碼中需要4個位元組的字元,在修正後的UTF-8編碼中將需要6個位元組。