字符編碼的知識(二)

  

3.偉大的創想Unicode

——不得不單獨說Unicode

像天朝一樣,當計算機傳到世界各個國家時,爲了適合當地語言和字符,設計和實現類似GB232/GBK/GB18030/BIG5的編碼方案。這樣各搞一套,在本地使用沒有問題,一旦出現在網絡中,由於不兼容,互相訪問就出現了亂碼現象。

爲了解決這個問題,一個偉大的創想產生了——UnicodeUnicode編碼系統爲表達任意語言的任意字符而設計。它使用4字節的數字來表達每個字母、符號,或者表意文字(ideograph)。每個數字代表唯一的至少在某種語言中使用的符號。(並不是所有的數字都用上了,但是總數已經超過了65535,所以2個字節的數字是不夠用的。)被幾種語言共用的字符通常使用相同的數字來編碼,除非存在一個在理的語源學(etymological)理由使不這樣做。不考慮這種情況的話,每個字符對應一個數字,每個數字對應一個字符。即不存在二義性。不再需要記錄"模式"了。U+0041總是代表'A',即使這種語言沒有'A'這個字符。

計算機科學領域中,Unicode統一碼萬國碼單一碼標準萬國碼)是業界的一種標準,它可以使電腦得以體現世界上數十種文字的系統。Unicode 是基於通用字符集Universal Character Set)的標準來發展,並且同時也以書本的形式[1]對外發表。Unicode 還不斷在擴增, 每個新版本插入更多新的字符。直至目前爲止的第六版,Unicode 就已經包含了超過十萬個字符(在2005Unicode 的第十萬個字符被採納且認可成爲標準之一)、一組可用以作爲視覺參考的代碼圖表、一套編碼方法與一組標準字符編碼、一套包含了上標字、下標字等字符特性的枚舉等。Unicode 組織(The Unicode Consortium)是由一個非營利性的機構所運作,並主導 Unicode 的後續發展,其目標在於:將既有的字符編碼方案以Unicode 編碼方案來加以取代,特別是既有的方案在多語環境下,皆僅有有限的空間以及不兼容的問題。

可以這樣理解:Unicode是字符集UTF-32/ UTF-16/ UTF-8是三種字符編碼方案

 

3.1.UCS & UNICODE

通用字符集Universal Character SetUCS)是由ISO制定的ISO 10646(或稱ISO/IEC 10646)標準所定義的標準字符集。歷史上存在兩個獨立的嘗試創立單一字符集的組織,即國際標準化組織(ISO)和多語言軟件製造商組成的統一碼聯盟。前者開發的 ISO/IEC 10646 項目,後者開發的統一碼項目。因此最初制定了不同的標準。

1991前後,兩個項目的參與者都認識到,世界不需要兩個不兼容的字符集。於是,它們開始合併雙方的工作成果,併爲創立一個單一編碼表而協同工作。從Unicode 2.0開始,Unicode採用了與ISO 10646-1相同的字庫和字碼;ISO也承諾,ISO 10646將不會替超出U+10FFFFUCS-4編碼賦值,以使得兩者保持一致。兩個項目仍都存在,並獨立地公佈各自的標準。但統一碼聯盟和ISO/IEC JTC1/SC2都同意保持兩者標準的碼錶兼容,並緊密地共同調整任何未來的擴展。在發佈的時候,Unicode一般都會採用有關字碼最常見的字型,但ISO 10646一般都儘可能採用Century字型

 

3.2.UTF-32

上述使用4字節的數字來表達每個字母、符號,或者表意文字(ideograph),每個數字代表唯一的至少在某種語言中使用的符號的編碼方案,稱爲UTF-32UTF-32又稱UCS-4是一種將Unicode字符編碼的協定,對每個字符都使用4字節。就空間而言,是非常沒有效率的。

這種方法有其優點,最重要的一點就是可以在常數時間內定位字符串裏的第N個字符,因爲第N個字符從第4×Nth個字節開始。雖然每一個碼位使用固定長定的字節看似方便,它並不如其它Unicode編碼使用得廣泛。

 

3.3.UTF-16

儘管有Unicode字符非常多,但是實際上大多數人不會用到超過前65535個以外的字符。因此,就有了另外一種Unicode編碼方式,叫做UTF-16(因爲16 = 2字節)UTF-160–65535範圍內的字符編碼成2個字節,如果真的需要表達那些很少使用的"星芒層(astral plane)"內超過這65535範圍的Unicode字符,則需要使用一些詭異的技巧來實現。UTF-16編碼最明顯的優點是它在空間效率上比UTF-32高兩倍,因爲每個字符只需要2個字節來存儲(除去65535範圍以外的),而不是UTF-32中的4個字節。並且,如果我們假設某個字符串不包含任何星芒層中的字符,那麼我們依然可以在常數時間內找到其中的第N個字符,直到它不成立爲止這總是一個不錯的推斷。其編碼方法是:

  • 如果字符編碼U小於0x10000,也就是十進制的065535之內,則直接使用兩字節表示;

  • 如果字符編碼U大於0x10000,由於UNICODE編碼範圍最大爲0x10FFFF,從0x100000x10FFFF之間 共有0xFFFFF個編碼,也就是需要20bit就可以標示這些編碼。用U'表示從0-0xFFFFF之間的值,將其前 10 bit作爲高位和16 bit的數值0xD800進行 邏輯or 操作,將後10 bit作爲低位和0xDC00 邏輯or操作,這樣組成的 4byte就構成了U的編碼。

對於UTF-32UTF-16編碼方式還有一些其他不明顯的缺點。不同的計算機系統會以不同的順序保存字節。這意味着字符U+4E2DUTF-16編碼方式下可能被保存爲4E 2D或者2D 4E,這取決於該系統使用的是大尾端(big-endian)還是小尾端(little-endian)(對於UTF-32編碼方式,則有更多種可能的字節排列。)只要文檔沒有離開你的計算機,它還是安全的——同一臺電腦上的不同程序使用相同的字節順序(byte order)。但是當我們需要在系統之間傳輸這個文檔的時候,也許在萬維網中,我們就需要一種方法來指示當前我們的字節是怎樣存儲的。不然的話,接收文檔的計算機就無法知道這兩個字節4E 2D表達的到底是U+4E2D還是U+2D4E

爲了解決這個問題,多字節的Unicode編碼方式定義了一個"字節順序標記(Byte Order Mark)",它是一個特殊的非打印字符,你可以把它包含在文檔的開頭來指示你所使用的字節順序。對於UTF-16,字節順序標記是U+FEFF。如果收到一個以字節FF FE開頭的UTF-16編碼的文檔,你就能確定它的字節順序是單向的(one way)的了;如果它以FE FF開頭,則可以確定字節順序反向了。

 

3.4.UTF-8

UTF-88-bit Unicode Transformation Format)是一種針對Unicode可變長度字符編碼定長碼),也是一種前綴碼它可以用來表示Unicode標準中的任何字符,且其編碼中的第一個字節仍與ASCII兼容,這使得原來處理ASCII字符的軟件無須或只須做少部份修改,即可繼續使用。因此,它逐漸成爲電子郵件網頁及其他存儲或傳送文字的應用中,優先採用的編碼。互聯網工程工作小組IETF)要求所有互聯網協議都必須支持UTF-8編碼。

UTF-8使用一至四個字節爲每個字符編碼

1.    128US-ASCII字符只需一個字節編碼(Unicode範圍由U+0000U+007F)。

2.    帶有附加符號拉丁文希臘文西裏爾字母亞美尼亞語希伯來文阿拉伯文敘利亞文它拿字母則需要二個字節編碼(Unicode範圍由U+0080U+07FF)。

3.    其他基本多文種平面BMP)中的字符(這包含了大部分常用字)使用三個字節編碼。

4.    其他極少使用的Unicode輔助平面的字符使用四字節編碼。

在處理經常會用到的ASCII字符方面非常有效。在處理擴展的拉丁字符集方面也不比UTF-16差。對於中文字符來說,比UTF-32要好。同時,(在這一條上你得相信我,因爲我不打算給你展示它的數學原理。)由位操作的天性使然,使用UTF-8不再存在字節順序的問題了。一份以utf-8編碼的文檔在不同的計算機之間是一樣的比特流。

總體來說,在Unicode字符串中不可能由碼點數量決定顯示它所需要的長度,或者顯示字符串之後在文本緩衝區中光標應該放置的位置;組合字符、變寬字體、不可打印字符和從右至左的文字都是其歸因。所以儘管在UTF-8字符串中字符數量與碼點數量的關係比UTF-32更爲複雜,在實際中很少會遇到有不同的情形。

優點

  • UTF-8ASCII的一個超集。因爲一個ASCII字符串也是一個合法的UTF-8字符串,所以現存的ASCII文本不需要轉換。爲傳統的擴展ASCII字符集設計的軟件通常可以不經修改或很少修改就能與UTF-8一起使用。

  • 使用標準的面向字節的排序例程對UTF-8排序將產生與基於Unicode代碼點排序相同的結果。(儘管這隻有有限的有用性,因爲在任何特定語言或文化下都不太可能有仍可接受的文字排列順序。)

  • UTF-8UTF-16都是可擴展標記語言文檔的標準編碼。所有其它編碼都必須通過顯式或文本聲明來指定。

  • 任何面向字節字符串搜索算法都可以用於UTF-8的數據(只要輸入僅由完整的UTF-8字符組成)。但是,對於包含字符記數的正則表達式或其它結構必須小心。

  • UTF-8字符串可以由一個簡單的算法可靠地識別出來。就是,一個字符串在任何其它編碼中表現爲合法的UTF-8的可能性很低,並隨字符串長度增長而減小。舉例說,字符值C0,C1,F5FF從來沒有出現。爲了更好的可靠性,可以使用正則表達式來統計非法過長和替代值(可以查看W3 FAQ: Multilingual Forms上的驗證UTF-8字符串的正則表達式)。

缺點

因爲每個字符使用不同數量的字節編碼,所以尋找串中第N個字符是一個O(N)複雜度的操作 — 即,串越長,則需要更多的時間來定位特定的字符。同時,還需要位變換來把字符編碼成字節,把字節解碼成字符。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章