UTF

變長字元編碼

UTF,是Unicode Transformation Format的縮寫,意為Unicode轉換格式。其中,UTF-8是UTF中最常用的轉換格式,是UNICODE的一種變長字元編碼,由KenThompson於1992年創建。現在已經標準化為RFC 3629。UTF-8用1到6個位元組編碼UNICODE字元。

簡介


UTF,是UnicodeTransformationFormat的縮寫,意為Unicode轉換格式。
如果UNICODE字元由2個位元組表示,則編碼成UTF-8很可能需要3個位元組,而如果UNICODE字元由4個位元組表示,則編碼成UTF-8可能需要6個位元組。用4個或6個位元組去編碼一個UNICODE字元可能太多了,但很少會遇到那樣的UNICODE字元。

簡史


ASCII碼

在所有字符集中,最知名可能要數被稱為ASCⅡ的7位字符集了。它是美國信息交換標準委員會(AmericanStandardCodeforInformationInterchange)的縮寫,為美國英語通信所設計。它由128個字元組成,包括大小寫字母、數字0-9、標點符號、非列印字元(換行符、製表符等4個)以及控制字元(退格、響鈴等)組成。標準的ASCII碼用一個位元組存儲,可以表示128個字元,其中最高位用作校驗碼。

擴展碼

但是,由於他是針對英語設計的,當處理帶有音調標號(形如漢語的拼音)的歐洲文字時就會出現問題。為了表示更多字元,人們打起了校驗碼的注意,讓最高位也用作字元表示,這就是ASCII碼擴字符集。ASCII擴展的字符集包括255個字元。其中有一種通常被稱為IBM字符集,它把值為128-255之間的字元用於畫圖和畫線,以及一些特殊的歐洲字元。另一種8位字符集是ISO8859-1Latin1,也簡稱為ISOLatin-1。它把位於128-255之間的字元用於拉丁字母表中特殊語言字元的編碼,也因此而得名。

編碼

歐洲語言不是地球上的唯一語言,因此亞洲和非洲語言並不能被8位字符集所支持。僅漢語(或pictograms)字母表就有80000以上個字元。但是把漢語、日語和越南語的一些相似的字元結合起來,在不同的語言里,使不同的字元代表不同的字,這樣只用2個位元組就可以編碼地球上幾乎所有地區的文字。因此,創建了UNICODE編碼。它通過增加一個高位元組對ISOLatin-1字符集進行擴展,當這些高位元組位為0時,低位元組就是ISOLatin-1字元。UNICODE支持歐洲、非洲、中東、亞洲(包括統一標準的東亞像形漢字和韓國像形文字)。但是,UNICODE並沒有提供對諸如Braille,Cherokee,Ethiopic,Khmer,Mongolian,Hmong,TaiLu,TaiMau文字的支持。同時它也不支持如Ahom,Akkadian,Aramaic,Babylonian、Cuneiform,Balti,Brahmi,Etruscan,Hittite,Javanese,Numidian,OldPersianCuneiform,Syrian之類的古老的文字。

轉換格式

事實證明,對可以用ASCII表示的字元使用UNICODE並不高效,因為UNICODE比ASCII佔用大一倍的空間,而對ASCII來說高位元組的0對他毫無用處。為了解決這個問題,就出現了一些中間格式的字符集,他們被稱為通用轉換格式,即UTF(UnicodeTransformationFormat)。目前存在的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。除非另外指定,否則大多數的位元組都是這樣的(Bigendianconvention)。將一個ASCII或Latin-1的文件轉換成UCS-2隻需簡單地在每個ASCII位元組前插入0x00。如果要轉換成UCS-4,則必須在每個ASCII位元組前插入三個0x00。
Unix下使用UCS-2(或UCS-4)會導致非常嚴重的問題。用這些編碼的字元串會包含一些特殊的字元,比如'\0'或'/',它們在文件名和其他C庫函數參數里都有特別的含義。另外,大多數使用ASCII文件的UNIX下的工具,如果不進行重大修改是無法讀取16位的字元的。基於這些原因,在文件名,文本文件,環境變數等地方,UCS-2不適合作為Unicode的外部編碼。
在ISO10646-1AnnexR和RFC2279里定義的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位元組長。
BigendianUCS-4位元組串的排列順序是預定的。
位元組0xFE和0xFF在UTF-8編碼中從未用到。
下列位元組串用來表示一個字元,用到哪個串取決於該字元在Unicode中的序號:
U-00000000-U-0000007F:0xxxxxxx
U-00000080-U-000007FF:110xxxxx10xxxxxx
U-00000800-U-0000FFFF:1110xxxx10xxxxxx10xxxxxx
U-00010000-U-001FFFFF:11110xxx10xxxxxx10xxxxxx10xxxxxx
U-00200000-U-03FFFFFF:111110xx10xxxxxx10xxxxxx10xxxxxx10xxxxxx
U-04000000-U-7FFFFFFF:1111110x10xxxxxx10xxxxxx10xxxxxx10xxxxxx10xxxxxx
xxx的位置由字元編碼數的二進位表示的位填入,越靠右的x具有越少的特殊意義,只用最短的那個足夠表達一個字元編碼數的多位元組串,注意在多位元組串中,第一個位元組的開頭"1"的數目就是整個串中位元組的數目。
例如:Unicode字元U+00A9=10101001(版權符號)在UTF-8里的編碼為:
11****1*1*1*1**1=0xC20xA9【註:*號代表0】
而字元U+2260=**1***1**11*****【註:*號代表0】(不等於)編碼為:
111****1*1***1***11*1*****=0xE20x890xA0
這種編碼的官方名字拼寫為UTF-8,其中UTF代表UCSTransformationFormat。請勿在任何文檔中用其他名字(比如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個位元組的字元ISOLatin-1是UNICODE的子集,但不是UTF-8的子集8位字元的UTF-8編碼會被email網關過濾,因為internet信息最初設計為7位ASCⅡ碼。因此產生了UTF-7編碼。UTF-8在它的表示中使用值100xxxxx的幾率超過50%,而現存的實現如ISO2022,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-BasicMultilingualPlain)的字元被編碼為4位元組格式,但是在修正的UTF-8編碼中,他們由代理編碼對(surrogatepairs)表示,然後這些代理編碼對在序列中分別重新編碼。結果標準UTF-8編碼中需要4個位元組的字元,在修正後的UTF-8編碼中將需要6個位元組。