百科解釋
目錄·歷史·描述·UTF-8的衍生物·設(shè)計(jì)UTF-8的理由·過長的資料排列(overlong forms)、輸入無效及保安的考慮·優(yōu)點(diǎn)及缺點(diǎn)·使用UTF-8的原因·UTF-8的編碼方式·UTF-8的特性·UTF-8編碼的缺點(diǎn) UTF-8(8 位元 Universal Character Set/Unicode Transformation Format)是針對Unicode 的一種可變長度字符編碼。它可以用來表示 Unicode 標(biāo)準(zhǔn)中的任何字符,而且其編碼中的第一個(gè)字節(jié)仍與 ASCII 相容,使得原來處理 ASCII 字符的軟件無需或只作少部份修改后,便可繼續(xù)使用。因此,它逐漸成為電子郵件、網(wǎng)頁及其他儲存或傳送文字的應(yīng)用中,優(yōu)先采用的編碼。 UTF-8 使用一至四個(gè)字節(jié)為每個(gè)字符編碼: 128 個(gè) US-ASCII 字符只需一個(gè)字節(jié)編碼(Unicode 范圍由 U+0000 至 U+007F)。 帶有變音符號的拉丁文、希臘文、西里爾字母、亞美尼亞語、希伯來文、阿拉伯文、敘利亞文及它拿字母則需要二個(gè)字節(jié)編碼(Unicode 范圍由 U+0080 至 U+07FF)。 其他基本多文種平面(BMP)中的字符(這包含了大部分常用字)使用三個(gè)字節(jié)編碼。 其他極少使用的 Unicode 輔助平面的字符使用四字節(jié)編碼。 對上述提及的第四種字符而言,UTF-8 使用四個(gè)字節(jié)來編碼似乎太耗費(fèi)資源了。但 UTF-8 對所有常用的字符都可以用三個(gè)字節(jié)表示,而且它的另一種選擇,UTF-16編碼,對前述的第四種字符同樣需要四個(gè)字節(jié)來編碼,所以要決定 UTF-8 或 UTF-16 哪種編碼比較有效率,還要視所使用的字符的分布范圍而定。不過,如果使用一些傳統(tǒng)的壓縮系統(tǒng),比如 DEFLATE,則這些不同編碼系統(tǒng)間的的差異就變得微不足道了。若顧及傳統(tǒng)壓縮算法在壓縮較短文字上的效果不大,可以考慮使用 Standard Compression Scheme for Unicode(SCSU)。 因特網(wǎng)工程工作小組(IETF)要求所有因特網(wǎng)協(xié)議都必須支援 UTF-8 編碼。[1] 互聯(lián)網(wǎng)郵件聯(lián)盟(IMC)建議所有電子郵件軟件都支援 UTF-8編碼。所有主要的電子郵件軟件中,只有 Eudora 不支援 UTF-8 編碼。[1] 歷史 1992年初,為建立良好的字節(jié)串編碼系統(tǒng)(byte-stream encoding)以供多字節(jié)字符集(multi-byte character sets)使用,開始了一個(gè)正式的研究。ISO/IEC 10646的初稿中有一個(gè)非必須的附錄,名為UTF。當(dāng)中包含了一個(gè)供32位元的字符使用的字節(jié)串編碼系統(tǒng)。這個(gè)編碼方式的性能并不令人滿意,但它提出了將0-127的范圍保留給ASCII以相容舊系統(tǒng)的概念。 1992年7月,X/Open委員會XoJIG開始尋求一個(gè)較佳的編碼系統(tǒng)。UNIX 系統(tǒng)實(shí)驗(yàn)室(UNIX System Laboratories, USL)的Dave Prosser為此提出了一個(gè)編碼系統(tǒng)的建議。它具備可更快速實(shí)作的特性,并引入一項(xiàng)新的改進(jìn)。其中,7位元的ASCII符號只代表原來的意思,所有多字節(jié)序列則會包含第8位元的符號,也就是所謂的最高有效位元。 1992年8月,這個(gè)建議由IBMX/Open的代表流傳到一些感興趣的團(tuán)體。與此同時(shí),貝爾實(shí)驗(yàn)室Plan 9操作系統(tǒng)工作小組的肯·湯普遜對這編碼系統(tǒng)作出重大的修改,讓編碼可以自我同步(self-synchronizing),使得不必從字串的開首讀取,也能找出字符間的分界。1992年9月2日,湯普遜和Pike一起在美國新澤西州一架餐車的餐桌墊上描繪出此設(shè)計(jì)的要點(diǎn)。接下來的日子,Pike及湯普遜將它實(shí)現(xiàn),并將這編碼系統(tǒng)完全應(yīng)用在Plan 9當(dāng)中,及后他將有關(guān)成果回饋X/Open。 1993年1月25-29日的在圣地牙哥舉行的USENIX會議首次正式介紹UTF-8。 自1996年起,微軟的CAB(MS Cabinet)規(guī)格在UTF-8標(biāo)準(zhǔn)正式落實(shí)前就明確容許在任何地方使用UTF-8編碼系統(tǒng)。但有關(guān)的編碼器實(shí)際上從來沒有實(shí)作這方面的規(guī)格。 描述 目前有好幾份關(guān)于UTF-8詳細(xì)規(guī)格的文件,但這些文件在定義上有些許的不同: RFC 3629 / STD 63(2003),這份文件制定了UTF-8是標(biāo)準(zhǔn)的因特網(wǎng)協(xié)議元素 第四版,The Unicode Standard,§3.9-§3.10(2003) ISO/IEC 10646-1:2000附加文件D(2000) 它們?nèi)〈艘韵履切┍惶蕴亩x: ISO/IEC 10646-1:1993修正案2/附加文件R(1996) 第二版,The Unicode Standard,附錄A(1996) RFC 2044(1996) RFC 2279(1998) 第三版,The Unicode Standard,§2.3(2000)及勘誤表#1:UTF-8 Shortest Form(2000) Unicode Standard 附加文件#27: Unicode 3.1(2001) 事實(shí)上,所有定義的基本原理都是相同的,它們之間最主要的不同是支援的字符范圍及無效輸入的處理方法。 Unicode字符的位元被分割為數(shù)個(gè)部分,并分配到UTF-8的字節(jié)串中較低的位元的位置。在U+0080的以下字符都使用內(nèi)含其字符的單字節(jié)編碼。這些編碼正好對應(yīng)7位元的ASCII字符。在其他情況,有可能需要多達(dá)4個(gè)字符組來表示一個(gè)字符。這些多字節(jié)的最高有效位元會設(shè)定成1,以防止與7位元的ASCII字符混淆,并保持標(biāo)準(zhǔn)的字節(jié)主導(dǎo)字串(standard byte-oriented string)運(yùn)作順利。 Unicode在范圍D800-DFFF中不存在任何字符,基本多文種平面中約定了這個(gè)范圍用于UTF-16擴(kuò)展標(biāo)識輔助平面(兩個(gè)UTF-16表示一個(gè)輔助平面字符). 當(dāng)然,任何編碼都是可以被轉(zhuǎn)換到這個(gè)范圍,但在unicode中他們并不代表任何合法的值 例如,希伯來語字母 aleph (?)的Unicode代碼是 U+05D0,按照以下方法改成 UTF-8: 它屬于 U+0080到U+07FF區(qū)域,這個(gè)表說明它使用雙字節(jié), 110yyyyy 10zzzzzz. 十六進(jìn)制 的 0x05D0換算成二進(jìn)制就是 101-1101-0000. 這11位數(shù)按順序放入"y"部分和"z"部分: 11010111 10010000. 最后結(jié)果就是雙字節(jié),用十六進(jìn)制寫起來就是 0xD7 0x90,這就是這個(gè)字符aleph (?)的UTF-8編碼。 所以開始的128個(gè)字符(US-ASCII)只需一字節(jié),接下來的1920個(gè)字符需要雙字節(jié)編碼,包括帶變音符號的拉丁字母, 希臘字母, 西里爾字母, 科普特語字母, 亞美尼亞語字母, 希伯來文字母和阿拉伯字母的字符;径辔姆N平面中其余的字符使用三個(gè)字節(jié),剩余字符使用四個(gè)字節(jié)。 根據(jù)這種方式可以處理更大數(shù)量的字符。原來的規(guī)范允許長達(dá)6字節(jié)的序列,可以覆蓋到31位元 (通用字符集原來的極限)。盡管如此,2003年11月UTF-8 被 RFC 3629 重新規(guī)范,只能使用原來Unicode定義的區(qū)域, U+0000到U+10FFFF。根據(jù)這些規(guī)范,以下字節(jié)值將無法出現(xiàn)在合法 UTF-8序列中: UTF-8的衍生物 Windows 雖然不是標(biāo)準(zhǔn),但許多Windows 程序(包括Windows 筆記本) 在UTF-8編碼的檔案的開首加入一段字節(jié)串EF BB BF。這是編碼成UTF-8的Byte Order Mark U+FEFF。沒有預(yù)期要處理UTF-8的文字編輯器和瀏覽器會會顯示為ISO-8859-1字符"???"。 Java 在通常用法下,Java程序語言在通過Template:Javadoc:SE 和Template:Javadoc:SE讀取和寫入串的時(shí)候支持標(biāo)準(zhǔn)UTF-8。但是,Java也支持一種非標(biāo)準(zhǔn)的變體UTF-8,供對象的系列化,Java本地界面和在class文件中的嵌入常數(shù)時(shí)使用的Template:Javadoc:SE。 標(biāo)準(zhǔn)和改正的UTF-8有兩個(gè)不同點(diǎn)。第一,空字符 (null character,U+0000)使用雙字節(jié),而不是單字節(jié),分別是11000000 10000000。這保證了在已編碼字串中沒有嵌入空字節(jié)。因?yàn)镃語言等語言程序中,單字節(jié)空字符是用來標(biāo)志串串結(jié)尾的。當(dāng)已編碼字串放到這樣的語言中處理,一個(gè)嵌入的空字符將把字串一刀兩斷。 第二個(gè)不同點(diǎn)是基本多文種平面之外字符的編碼的方法。在標(biāo)準(zhǔn)UTF-8中,這些字符使用4字節(jié)形式編碼,而在改正的UTF-8中,這些字符和UTF-16一樣首先表示為代理對(surrogate pairs),然后再像CESU-8那樣按照代理對分別編碼。這樣改正的原因更是微妙。Java中的字符為16位長,因此一些Unicode字符需要兩個(gè)Java字符來表示。語言的這個(gè)性質(zhì)蓋過了Unicode的增補(bǔ)平面的要求。盡管如此,為了要保持良好的向后兼容、要改變也不容易了。這個(gè)改正的編碼系統(tǒng)保證了一個(gè)已編碼字串可以一次編為一個(gè)UTF-16碼,而不是一次一個(gè)Unicode碼點(diǎn)。 不幸的是,這也意味著UTF-8中需要4字節(jié)的字符在改正UTF-8中變成需要6字節(jié)。 因?yàn)楦恼腢TF-8并不是 UTF-8,所以用戶在交換信息和使用互聯(lián)網(wǎng)的時(shí)候需要特別注意不要誤把改正UTF-8當(dāng)成UTF-8數(shù)據(jù)。 Mac OS X Mac OS X操作系統(tǒng)使用正式分解萬國碼(canonically decomposed Unicode),在文件系統(tǒng)中使用UTF-8編碼進(jìn)行文件命名,這做法通常被稱為UTF-8-MAC。正式分解萬國碼中,預(yù)分解字符是被禁止使用的,必須以組合字符取代。 這種方法使分類變得非常簡單,但是會搞混那些使用預(yù)分解字符為標(biāo)準(zhǔn)、組合字符用來顯示特殊字符的軟件。Mac系統(tǒng)的這種NFD數(shù)據(jù)是萬國碼規(guī)范化(Unicode normalization)的一種格式。而其他系統(tǒng), 包括Windows和 Linux, 使用萬國碼規(guī)范的NFC形式,也是W3C標(biāo)準(zhǔn)使用的形式。所以NFD數(shù)據(jù)必須典型的轉(zhuǎn)換成NFC才能被其他平臺或者網(wǎng)絡(luò)使用。 在此有關(guān)于此問題的討論 Apple Q&A 1173. 設(shè)計(jì)UTF-8的理由 UTF-8的設(shè)計(jì)有以下的多字符組序列的特質(zhì): 單字節(jié)字符的最高有效位元永遠(yuǎn)為0。 多字節(jié)序列中的首個(gè)字符組的幾個(gè)最高有效位元決定了序列的長度。最高有效位為<code>110</code>的是2字節(jié)序列,而<code>1110</code>的是三字節(jié)序列,如此類推。 多字節(jié)序列中其余的字節(jié)中的首兩個(gè)最高有效位元為<code>10</code>。 UTF-8的這些特質(zhì),保證了一個(gè)字符的字節(jié)序列不會包含在另一個(gè)字符的字節(jié)序列中。這確保了以字節(jié)為基礎(chǔ)的部份字串比對(sub-string match)方法可以適用于在文字中搜尋字或詞。有些比較舊的可變長度8位元編碼(如Shift-JIS)沒有這個(gè)特質(zhì),故字串比對的算法變得相當(dāng)復(fù)雜。雖然這增加了UTF-8編碼的字串的冗余,但是利多于弊。另外,資料壓縮并非Unicode 的目的,所以不可混為一談。即使在傳送過程中有部份字節(jié)因錯(cuò)誤或干擾而完全遺失,還是有可能在下一個(gè)字符的起點(diǎn)重新同步,令受損范圍受到限制。 另一方面,由于其字節(jié)序列設(shè)計(jì),如果一個(gè)疑似為字符串的序列被驗(yàn)證為UTF-8編碼,那么我們可以有把握地說它是UTF-8字符串。一段兩字節(jié)隨機(jī)序列碰巧為合法的UTF-8而非ASCII 的機(jī)率為32分1。對于三字節(jié)序列的機(jī)率為256分3,對更長的序列的機(jī)率就更低了。 過長的資料排列(overlong forms)、輸入無效及保安的考慮 優(yōu)點(diǎn)及缺點(diǎn) 關(guān)于字符串長度的一個(gè)注解: 總體來說,在Unicode字符串中不可能由碼點(diǎn)數(shù)量決定顯示它所需要的長度,或者顯示字符串之后在文本緩沖區(qū)中光標(biāo)應(yīng)該放置的位置;組合字符、變寬字體、不可打印字符和從右至左的文字都是其歸因。 所以盡管在UTF-8字符串中字符數(shù)量與碼點(diǎn)數(shù)量的關(guān)系比UTF-32更為復(fù)雜,在實(shí)際中很少會遇到有不同的情形。 總體 優(yōu)點(diǎn) UTF-8是ASCII的一個(gè)超集。因?yàn)橐粋(gè)純ASCII字符串也是一個(gè)合法的UTF-8字符串,所以現(xiàn)存的ASCII文本不需要轉(zhuǎn)換。為傳統(tǒng)的擴(kuò)展ASCII字符集設(shè)計(jì)的軟件通?梢圆唤(jīng)修改或很少修改就能與UTF-8一起使用。 使用標(biāo)準(zhǔn)的面向字節(jié)的排序例程對UTF-8排序?qū)a(chǎn)生與基于Unicode代碼點(diǎn)排序相同的結(jié)果。(盡管這只有有限的有用性,因?yàn)樵谌魏翁囟ㄕZ言或文化下都不太可能有仍可接受的文字排列順序。) UTF-8和UTF-16都是擴(kuò)展標(biāo)記語言文檔的標(biāo)準(zhǔn)編碼。所有其它編碼都必須通過顯式或文本聲明來指定。[2] 任何面向字節(jié)的字符串搜索算法都可以用于UTF-8的數(shù)據(jù)(只要輸入僅由完整的UTF-8字符組成)。但是,對于包含字符記數(shù)的正則表達(dá)式或其它結(jié)構(gòu)必須小心。 UTF-8字符串可以由一個(gè)簡單的算法可靠地識別出來。就是,一個(gè)字符串在任何其它編碼中表現(xiàn)為合法的UTF-8的可能性很低,并隨字符串長度增長而減小。舉例說,字符值C0,C1,F5至FF從來沒有出現(xiàn)。為了更好的可靠性,可以使用正則表達(dá)式來統(tǒng)計(jì)非法過長和替代值(可以查看W3 FAQ: Multilingual Forms上的驗(yàn)證UTF-8字符串的正則表達(dá)式)。 缺點(diǎn) 一份寫得很差(并且與當(dāng)前標(biāo)準(zhǔn)的版本不兼容)的UTF-8解析器可能會接受一些不同的偽UTF-8表示并將它們轉(zhuǎn)換到相同的Unicode輸出上。這為設(shè)計(jì)用于處理八位表示的校驗(yàn)例程提供了一種遺漏信息的方式。 使用UTF-8的原因 ASCII轉(zhuǎn)換成UCS-2,在編碼前插入一個(gè)0x0。用這些編碼,會含括一些控制符,比如 " 或 &#39;&#39;&#39;&#39;/&#39;&#39;&#39;&#39;,這在UNIX和一些C函數(shù)中,將會產(chǎn)生嚴(yán)重錯(cuò)誤。因此可以肯定,UCS-2不適合作為Unicode的外部編碼,也因此誕生了UTF-8。 UTF-8的編碼方式 UTF-8是UNICODE的一種變長度的編碼表達(dá)方式 〈一般UNICODE為雙字節(jié)(指UCS2)〉,它由Ken Thompson于1992年建立,現(xiàn)在已經(jīng)標(biāo)準(zhǔn)化為RFC 3629。UTF-8就是以8位為單元對UCS進(jìn)行編碼,而UTF-8不使用大尾序和小尾序的形式,每個(gè)使用UTF-8儲存的字符,除了第一個(gè)字節(jié)外,其余字節(jié)的頭兩個(gè)位元都是以 "10" 開始,使文字處理器能夠較快地找出每個(gè)字符的開始位置。 但為了與以前的ASCII碼相容 (ASCII為一個(gè)字節(jié)),因此 UTF-8 選擇了使用可變長度字節(jié)來儲存 Unicode: 在ASCII碼的范圍,用一個(gè)字節(jié)表示,超出ASCII碼的范圍就用字節(jié)表示,這就形成了我們上面看到的UTF-8的表示方法,這様?shù)暮锰幨钱?dāng)UNICODE文件中只有ASCII碼時(shí),儲存的文件都為一個(gè)字節(jié),所以就是普通的ASCII文件無異,讀取的時(shí)候也是如此,所以能與以前的ASCII文件相容。 大于ASCII碼的,就會由上面的第一字節(jié)的前幾位表示該unicode字符的長度,比如110xxxxxx前三位的二進(jìn)制表示告訴我們這是個(gè) 2BYTE的UNICODE字符;1110xxxx是個(gè)三位的UNICODE字符,依此類推;xxx 的位置由字符編碼數(shù)的二進(jìn)制表示的位填入. 越靠右的 x 具有越少的特殊意義.只用最短的那個(gè)足夠表達(dá)一個(gè)字符編碼數(shù)的多字節(jié)串. 注意在多字節(jié)串中, 第一個(gè)字節(jié)的開頭"1"的數(shù)目就是整個(gè)串中字節(jié)的數(shù)目.。 ASCII字母繼續(xù)使用1字節(jié)儲存,重音文字、希臘字母或西里爾字母等使用2字節(jié)來儲存,而常用的漢字就要使用3字節(jié)。輔助平面字符則使用4字節(jié)。 在UTF-8文件的開首,很多時(shí)都放置一個(gè)U+FEFF字符 (UTF-8 以 EF,BB,BF 代表),以顯示這個(gè)文字檔案是以UTF-8編碼。 UTF-8的特性 UCS 字符 U+0000 到 U+007F (ASCII) 被編碼為字節(jié) 0x00 到 0x7F (ASCII 兼容),這也意味著只包含 7 位 ASCII 字符的文件在 ASCII 和 UTF-8 兩種編碼方式下是一樣的. 所有 >U+007F 的 UCS 字符被編碼為一個(gè)多個(gè)字節(jié)的串, 每個(gè)字節(jié)都有標(biāo)記位集。因此,ASCII 字節(jié) (0x00-0x7F) 不可能作為任何其他字符的一部分。 表示非 ASCII 字符的多字節(jié)串的第一個(gè)字節(jié)總是在 0xC0 到 0xFD 的范圍里,并指出這個(gè)字符包含多少個(gè)字節(jié)。多字節(jié)串的其余字節(jié)都在 0x80 到 0xBF 范圍里,這使得重新同步非常容易,并使編碼無國界,且很少受丟失字節(jié)的影響。 可以編入所有可能的 231個(gè) UCS 代碼 UTF-8 編碼字符理論上可以最多到 6 個(gè)字節(jié)長, 然而 16 位 BMP 字符最多只用到 3 字節(jié)長。 Bigendian UCS-4 字節(jié)串的排列順序是預(yù)定的。 字節(jié) 0xFE 和 0xFF 在 UTF-8 編碼中從未用到,同時(shí),UTF-8以字節(jié)為編碼單元,它的字節(jié)順序在所有系統(tǒng)中都是一様?shù),沒有字節(jié)序的問題,也因此它實(shí)際上并不需要BOM。 與 UTF-16 或其他 Unicode 編碼相比,對于不支援 Unicode 和 XML 的系統(tǒng),UTF-8 更不容易造成問題。 【注】 UTF為UCS / Unicode Transformation Format“Unicode轉(zhuǎn)換格式”的縮寫。 UCS的中文全稱為:信息技術(shù)--通用多八位編碼字符集 (Universal Multi-octet Coded Character Set),由ISO/IEC 10646 標(biāo)準(zhǔn)描述。 UTF-8編碼的缺點(diǎn) 不利于正則表達(dá)式檢索 正則表達(dá)式可以進(jìn)行很多英文高級的模糊檢索。例如,[a-h]表示a到h間所有字母。 同樣GBK編碼的中文也可以這樣利用正則表達(dá)式,比如在只知道一個(gè)字的讀音而不知道怎么寫的情況下,也可用正則表達(dá)式檢索,因?yàn)镚BK編碼是按讀音排序的。只是UTF-8不是按讀音排序的,所以會對正則表達(dá)式檢索造成不利影響。但是這種使用方式并未考慮中文中的破音字,因此影響不大。Unicode是按部首排序的,因此在只知道一個(gè)字的部首而不知道如何發(fā)音的情況下,UTF-8 可用正則表達(dá)式檢索而GBK不行。 其他 與其他 Unicode 編碼相比,特別是UTF-16,在 UTF-8 中 ASCII 字符占用的空間只有一半,可是在一些字符的 UTF-8 編碼占用的空間就要多出,特別是中文、日文和韓文(CJK)這樣的象形文字,所以具體因素因文檔而異,但不論哪種情況,差別都不可能很明顯。
移動通信網(wǎng) | 通信人才網(wǎng) | 更新日志 | 團(tuán)隊(duì)博客 | 免責(zé)聲明 | 關(guān)于詞典 | 幫助