UTF-8(8-bit Unicode Transformation Format)是一種針對(duì)Unicode的可變長度字符編碼,又稱萬國碼,由Ken Thompson于1992年創(chuàng)建。現(xiàn)在已經(jīng)標(biāo)準(zhǔn)化為RFC 3629。UTF-8用1到6個(gè)字節(jié)編碼Unicode字符。用在網(wǎng)頁上可以統(tǒng)一頁面顯示中文簡體繁體及其它語言(如英文,日文,韓文)。1
發(fā)展歷程在所有字符集中,最知名的可能要數(shù)被稱為ASCII的7位字符集了。它是美國標(biāo)準(zhǔn)信息交換代碼(American Standard Code for Information Interchange)的縮寫, 為美國英語通信所設(shè)計(jì)。它由128個(gè)字符組成,包括大小寫字母、數(shù)字0-9、標(biāo)點(diǎn)符號(hào)、非打印字符(換行符、制表符等4個(gè))以及控制字符(退格、響鈴等)組成。
但是,由于它是針對(duì)英語設(shè)計(jì)的,當(dāng)處理帶有音調(diào)標(biāo)號(hào)(形如漢語的拼音)的亞洲文字時(shí)就會(huì)出現(xiàn)問題。因此,創(chuàng)建出了一些包括255個(gè)字符的由ASCII擴(kuò)展的字符集。其中有一種通常被稱為IBM字符集,它把值為128-255之間的字符用于畫圖和畫線,以及一些特殊的歐洲字符。另一種8位字符集是ISO 8859-1Latin 1,也簡稱為ISOLatin-1。它把位于128-255之間的字符用于拉丁字母表中特殊語言字符的編碼,也因此而得名。歐洲語言不是地球上的唯一語言,因此亞洲和非洲語言并不能被8位字符集所支持。僅漢語字母表(或pictograms)就有80000以上個(gè)字符。但是把漢語、日語和越南語的一些相似的字符結(jié)合起來,在不同的語言里,使不同的字符代表不同的字,這樣只用2個(gè)字節(jié)就可以編碼地球上幾乎所有地區(qū)的文字。因此,創(chuàng)建了UNICODE編碼。它通過增加一個(gè)高字節(jié)對(duì)ISO Latin-1字符集進(jìn)行擴(kuò)展,當(dāng)這些高字節(jié)位為0時(shí),低字節(jié)就是ISO Latin-1字符。UNICODE支持歐洲、非洲、中東、亞洲(包括統(tǒng)一標(biāo)準(zhǔn)的東亞象形漢字和韓國表音文字)。但是,UNICODE并沒有提供對(duì)諸如Braille(盲文),Cherokee, Ethiopic(埃塞俄比亞語), Khmer(高棉語), Mongolian(蒙古語), Hmong(苗語), Tai Lu, Tai Mau文字的支持。同時(shí)它也不支持如Ahom(阿霍姆語), Akkadian(阿卡德語), Aramaic(阿拉米語), Babylonian Cuneiform(古巴比倫楔形文字), Balti(巴爾蒂語), Brahmi(婆羅米文), Etruscan(伊特拉斯坎語), Hittite(赫梯語/西臺(tái)語), Javanese(爪哇語), Numidian(努米底亞語), Old Persian Cuneiform(古波斯楔形文字), Syrian(敘利亞語)之類的古老文字。
事實(shí)證明,對(duì)可以用ASCII表示的字符使用UNICODE并不高效,因?yàn)閁NICODE比ASCII占用大一倍的空間,而對(duì)ASCII來說高字節(jié)的0對(duì)他毫無用處。為了解決這個(gè)問題,就出現(xiàn)了一些中間格式的字符集,他們被稱為通用轉(zhuǎn)換格式,即UTF(Unicode Transformation Format)。常見的UTF格式有:UTF-7, UTF-7.5, UTF-8,UTF-16, 以及 UTF-32。2
字符集如果UNICODE字符由2個(gè)字節(jié)表示,則編碼成UTF-8很可能需要3個(gè)字節(jié)。而如果UNICODE字符由4個(gè)字節(jié)表示,則編碼成UTF-8可能需要6個(gè)字節(jié)。用4個(gè)或6個(gè)字節(jié)去編碼一個(gè)UNICODE字符可能太多了,但很少會(huì)遇到那樣的UNICODE字符。3
UTF-8編碼規(guī)則:如果只有一個(gè)字節(jié)則其最高二進(jìn)制位為0;如果是多字節(jié),其第一個(gè)字節(jié)從最高位開始,連續(xù)的二進(jìn)制位值為1的個(gè)數(shù)決定了其編碼的字節(jié)數(shù),其余各字節(jié)均以10開頭。UTF-8轉(zhuǎn)換表表示如下:
|| || 表一 UTF-8轉(zhuǎn)換表
實(shí)際表示ASCII字符的UNICODE字符,將會(huì)編碼成1個(gè)字節(jié),并且UTF-8表示與ASCII字符表示是一樣的。所有其他的UNICODE字符轉(zhuǎn)化成UTF-8將需要至少2個(gè)字節(jié)。每個(gè)字節(jié)由一個(gè)換碼序列開始。第一個(gè)字節(jié)由唯一的換碼序列,由n位連續(xù)的1加一位0組成, 首字節(jié)連續(xù)的1的個(gè)數(shù)表示字符編碼所需的字節(jié)數(shù)。
Unicode轉(zhuǎn)換為UTF-8時(shí),可以將Unicode二進(jìn)制從低位往高位取出二進(jìn)制數(shù)字,每次取6位,如上述的二進(jìn)制就可以分別取出為如下示例所示的格式,前面按格式填補(bǔ),不足8位用0填補(bǔ)。
注:Unicode轉(zhuǎn)換為UTF-8需要的字節(jié)數(shù)可以根據(jù)這個(gè)規(guī)則計(jì)算:如果Unicode小于0X80(Ascii字符),則轉(zhuǎn)換后為1個(gè)字節(jié)。否則轉(zhuǎn)換后的字節(jié)數(shù)為Unicode二進(jìn)制位數(shù)+3再除以5。
示例
UNICODE uCA(1100 1010) 編碼成UTF-8將需要2個(gè)字節(jié):
uCA C3 8A, 過程如下:
uCA(1100 1010)處于0080 ~07FF之間,從上文中的轉(zhuǎn)換表可知對(duì)其編碼需要2bytes,即兩個(gè)字節(jié),其對(duì) 應(yīng) UTF-8格式為: 110X XXXX10XX XXXX。從此格式中可以看到,對(duì)其編碼還需要11位,而uCA(1100 1010)僅有8位,這時(shí)需要在其二進(jìn)制數(shù)前補(bǔ)0湊成11位: 000 1100 1010, 依次填入110X XXXX 10XX XXXX的空位中, 即得 1100 0011 1000 1010(C38A)。
同理,UNICODE uF03F (1111 0000 0011 1111) 編碼成UTF-8將需要3個(gè)字節(jié):
u F03F EF 80 BF,對(duì)應(yīng)格式為:1110XXXX10XX XXXX10XX XXXX,編碼還需要16位,將1111 0000 0011 1111(F03F)依次填入,可得 1110 1111 1000 0000 1011 1111(EF 80 BF)。
優(yōu)缺點(diǎn)優(yōu)點(diǎn)UTF-8編碼可以通過屏蔽位和移位操作快速讀寫。字符串比較時(shí)strcmp()和wcscmp()的返回結(jié)果相同,因此使排序變得更加容易。字節(jié)FF和FE在UTF-8編碼中永遠(yuǎn)不會(huì)出現(xiàn),因此他們可以用來表明UTF-16或UTF-32文本(見BOM) UTF-8 是字節(jié)順序無關(guān)的。它的字節(jié)順序在所有系統(tǒng)中都是一樣的,因此它實(shí)際上并不需要BOM。4
缺點(diǎn)你無法從UNICODE字符數(shù)判斷出UTF-8文本的字節(jié)數(shù),因?yàn)閁TF-8是一種變長編碼它需要用2個(gè)字節(jié)編碼那些用擴(kuò)展ASCII字符集只需1個(gè)字節(jié)的字符 ISO Latin-1 是UNICODE的子集,但不是UTF-8的子集 8位字符的UTF-8編碼會(huì)被email網(wǎng)關(guān)過濾,因?yàn)閕nternet信息最初設(shè)計(jì)為7位ASCII碼。因此產(chǎn)生了UTF-7編碼。 UTF-8 在它的表示中使用值100xxxxx的幾率超過50%, 而現(xiàn)存的實(shí)現(xiàn)如ISO 2022, 4873, 6429, 和8859系統(tǒng),會(huì)把它錯(cuò)認(rèn)為是C1 控制碼。因此產(chǎn)生了UTF-7.5編碼。4
修正更新java使用UTF-16表示內(nèi)部文本,并支持用于字符串串行化的非標(biāo)準(zhǔn)的修正UTF-8編碼。標(biāo)準(zhǔn)UTF-8和修正的UTF-8有兩點(diǎn)不同:
修正的UTF-8中,null字符編碼成2個(gè)字節(jié)(1100000010000000)而不是標(biāo)準(zhǔn)的1個(gè)字節(jié)(00000000),這樣做可以保證編碼后的字符串中不會(huì)嵌入null字符。因此如果在類C語言中處理字符串,文本不會(huì)在第一個(gè)null字符時(shí)截?cái)啵–字符串以'\0'結(jié)尾)。
在標(biāo)準(zhǔn)UTF-8編碼中,超出基本多語言范圍(BMP-Basic Multilingual Plane)的字符被編碼為4字節(jié)格式,但是在修正的UTF-8編碼中,他們由代理編碼對(duì)(surrogatepairs)表示,然后這些代理編碼對(duì)在序列中分別重新編碼。結(jié)果標(biāo)準(zhǔn)UTF-8編碼中需要4個(gè)字節(jié)的字符,在修正后的UTF-8編碼中將需要6個(gè)字節(jié)。5
本詞條內(nèi)容貢獻(xiàn)者為:
徐恒山 - 講師 - 西北農(nóng)林科技大學(xué)