Character Encoding Summary

Brief Evolution History

Chinese Encoding Roadmap

Character Encoding System Hierarchy
   Character --> Code Point --> Encoding Scheme
  首先,我們需要確定對哪些字符進行編碼;然後我們要分配給每個字符一個唯一的編碼值;最後我們要知道如何表示這個編碼值,是直接存儲這個編碼值,還是對編碼值進行變化(比如,UTF-8,UTF-16)。
I.ISO 

1. ASCII
 全稱是American Standard Code for Information Interchange。它是由美國標準協會(最初名稱是American Standards Association--ASA, 後來改名爲American Nation Standards Institute--ANSI)上個世紀50年代開發。它是一個英文字表系統的字符編碼體系。總共128個字符,包括1)數字0-9;2)字母a-z,A-Z;3)一些標點符號;4)控制符號;5)空格。


2. ISO 646

ISO 646對ASCII進行擴展,對非英語國家的字符進行編碼,但仍然是7位字符的字符集。英語字母和數字部分,爲所有國家相同外,有些使用字母的國家,可按照實際需要,把 ISO 646 修改,以定出該國的字符標準。下面這張圖顯示了ISO 646的字符集。灰色陰影部分隨地區變化而變化。


下表列出了不同國家的變化


中國基於ISO-646的標準是GB1988-80,主要變化就是0x24的字符是人民幣的符號“¥”,以及0x7E是"-".

3. ISO 2022

1) ISO 646雖然是對ASCII進行了擴展,但畢竟是7位編碼,其擴展是有限的。而這時的通信領域的協議採用了第8位做校驗糾錯用途,但是,對於計算機內存來說,校驗糾錯變得不是必要。因此8位字符編碼逐漸出現,用來表示比ASCII碼更多的字符。爲此,1971年公佈的ECMA-35標準,用來規定各種7位或8位字符編碼應當遵從的共同規則。隨後ECMA-35被採納爲ISO 2022. 

英語可用7位編碼儲存,而其他使用拉丁字母、希臘字母、西裏爾字母、希伯來字母等的語文,由於只使用數十個字母,傳統上均使用8位編碼的ISO/IEC 8859標準來表示。但由於漢語、日語及朝鮮語字數衆多,無法用單一個8位字符來表達,故需要多於一個字節來代表一個字。於是,ISO 2022就設計出來讓漢語、日語及朝鮮語可以使用數個8位編碼的字符來示。

ISO 2022使用“轉義符串”(Escape sequence)。轉義符串由1個“ESC”字符(0x1B),再由兩至三個字串組成。此標記代表它後面的字符,屬於下表字符集的文字。

2)ISO 2022定義了一規則,如何進行7位或者8位編碼,但是沒有具體定義某個字符集是如何編碼。 ISO 8859則是在ISO 2022基礎上定義了一系列字符集的編碼標準。
  • ISO/IEC 8859-1 (Latin-1) - 西歐語言
  • ISO/IEC 8859-2 (Latin-2) - 中歐語言
  • ISO/IEC 8859-3 (Latin-3) - 南歐語言
  • ISO/IEC 8859-4 (Latin-4) - 北歐語言
  • ISO/IEC 8859-5 (Cyrillic) - 斯拉夫語言
  • ISO/IEC 8859-6 (Arabic) - 阿拉伯語
  • ISO/IEC 8859-7 (Greek) - 希臘語
  • ISO/IEC 8859-8 (Hebrew) - 希伯來語(視覺順序)
  •       ISO 8859-8-I - 希伯來語(邏輯順序)
  • ISO/IEC 8859-9(Latin-5 或 Turkish)- 它把Latin-1的冰島語字母換走,加入土耳其語字母。
  • ISO/IEC 8859-10(Latin-6 或 Nordic)- 北日耳曼語支,用來代替Latin-4。
  • ISO/IEC 8859-11 (Thai) - 泰語,從泰國的 TIS620 標準字集演化而來。
  • ISO/IEC 8859-13(Latin-7 或 Baltic Rim)- 波羅的語族
  • ISO/IEC 8859-14(Latin-8 或 Celtic)- 凱爾特語族
  • ISO/IEC 8859-15 (Latin-9) - 西歐語言,加入Latin-1欠缺的芬蘭語字母和大寫法語重音字母,以及歐元(€)符號。
  • ISO/IEC 8859-16 (Latin-10) - 東南歐語言。主要供羅馬尼亞語使用,並加入歐元符號
3)ISO 2022的亮點就是支持中、日、韓的文字。
  • ISO-2022-JP. A widely used encoding for Japanese. Starts in ASCII and includes the following escape sequences ESC ( B to switch to ASCII (1 byte per character)
ESC ( J to switch to JIS X 0201-1976 (ISO/IEC 646:JP) Roman set (1 byte per character)
ESC $ @ to switch to JIS X 0208-1978 (2 bytes per character)
ESC $ B to switch to JIS X 0208-1983 (2 bytes per character)
  • ISO-2022-JP-1. The same as ISO-2022-JP with one additional escape sequence ESC $ ( D to switch to JIS X 0212-1990 (2 bytes per character)
  • ISO-2022-JP-2. A multilingual extension of ISO-2022-JP. The same as ISO-2022-JP-1 with the following additional escape sequences [1] ESC $ A to switch to GB 2312-1980 (2 bytes per character)
ESC $ ( C to switch to KS X 1001-1992 (2 bytes per character)
ESC . A to switch to ISO/IEC 8859-1 high part, Extended Latin 1 set (1 byte per character) [designated to G2]
ESC . F to switch to ISO/IEC 8859-7 high part, Basic Greek set (1 byte per character) [designated to G2]
  • ISO-2022-JP-3. The same as ISO-2022-JP with three additional escape sequences ESC ( I to switch to JIS X 0201-1976 Kana set (1 byte per character)
ESC $ ( O to switch to JIS X 0213-2000 Plane 1 (2 bytes per character)
ESC $ ( P to switch to JIS X 0213-2000 Plane 2 (2 bytes per character)

  • ISO-2022-JP-2004. The same as ISO-2022-JP-3 with one additional escape sequence      
                   ESC $ ( Q to switch to JIS X 0213-2004 Plane 1 (2 bytes per character)
  • ISO-2022-KR. An encoding for Korean.  
                   ESC $ ) C to switch to KS X 1001-1992,[2][3] previously named KS C 5601-1987 (2 bytes per character) [designated to G1]
  • ISO-2022-CN. An encoding for Chinese. 
                    ESC $ ) A to switch to GB 2312-1980 (2 bytes per character) [designated to G1]
ESC $ ) G to switch to CNS 11643-1992 Plane 1 (2 bytes per character) [designated to G1]
ESC $ * H to switch to CNS 11643-1992 Plane 2 (2 bytes per character)
  • ISO-2022-CN-EXT. The same as ISO-2022-CN with six additional escape sequence
                    ESC $ ) E to switch to ISO-IR-165 (2 bytes per character) [designated to G1]
ESC $ + I to switch to CNS 11643-1992 Plane 3 (2 bytes per character) [designated to G3]
ESC $ + J to switch to CNS 11643-1992 Plane 4 (2 bytes per character) [designated to G3]
ESC $ + K to switch to CNS 11643-1992 Plane 5 (2 bytes per character) [designated to G3]
ESC $ + L to switch to CNS 11643-1992 Plane 6 (2 bytes per character) [designated to G3]
ESC $ + M to switch to CNS 11643-1992 Plane 7 (2 bytes per character) [designated to G3]

    4) 按照標準,漢字編碼以下面的形式出現:
       逃逸字符串 + 轉換控制符(轉爲逃逸字符串代表的字符編碼) + 漢字國標碼( 區位碼H+20H,H表示十六進制) +轉換控制符(轉爲ASCII,是SI,十六進制是0F).
    
   例如, 按照GB2312給"交換"編碼:
      "交"的區位碼是2927,十六進制是1D1B. 對應國標碼是3D3B.
      “換”的區位碼是2727,十六進制是1B1B. 對應國標碼是3B3B.
      ESC $ ) A表示接下來的編碼符號GB2312標準。GB2312的轉換控制符是S0,十六進制是0E.
     所以編碼是:
     1B 24 29 41 0E 3D 3B 3B 3B 0F.
     "1B 24 29 41" 就是“ESC $ ) A”對應的ASCII 編碼; "3D 3B 3B 3B" 就是“交換”的GB2312編碼; “0E” 是轉換字符,和"ESC $ ) A"表示它後面的字符是GB2312編碼漢字‘; "0F"也是控制字符,表示後面的字符是ASCII編碼.
    
    

4. ISO 10646 和 Unicode
1. 簡述
ISO10646,定義了通用字符集(UCS--Universal Character Set),包含了已知語言的所有字符集。用一個標準來處理所有的字符,使得字符編碼變的統一和簡單。ISO 10646 定義了一個 31 位的字符集. 最經常使用的字符在第一平面(0x0000--0xFFFD),這個 UCS 的 16位子集稱爲 基本多語言面 (Basic Multilingual Plane, BMP). 被編碼在 16 位 BMP 以外的字符都屬於非常特殊的字符(比如象形文字), 且只有專家在歷史和科學領域裏纔會用到它們. 按當前的計劃, 將來也許再也不會有字符被分配到從 0x000000 到 0x10FFFF 這個覆蓋了超過 100 萬個潛在的未來字符的 21 位的編碼空間以外去了.
用"U+XXXX"來表示一個字符的編碼. 比如U+0041表示字母“A”. 值"XXXX"稱爲對應字符的代碼點(code point).

2. 和Unicode的關係
 歷史上, 有兩個獨立的, 創立單一字符集的嘗試. 一個是國際標準化組織(ISO)的 ISO 10646 項目, 另一個是由(一開始大多是美國的)多語言軟件製造商組成的協會(Unicode Consortium)組織的 Unicode 項目. 幸運的是, 1991年前後, 兩個項目的參與者都認識到, 世界不需要兩個不同的單一字符集. 它們合併雙方的工作成果, 併爲創立一個單一編碼表而協同工作. 兩個項目仍都存在並獨立地公佈各自的標準, 但 Unicode 協會和 ISO/IEC JTC1/SC2 都同意保持 Unicode 和 ISO 10646 標準的碼錶兼容, 並緊密地共同調整任何未來的擴展

3. 組合字符和實現層次
UCS-2 編碼了很多組合字符(combining character),也稱爲表示浮動發音符的無間距標記。在包括印度語、泰國語、阿拉伯語和希伯來語在內的多種文字體系中,這些字符是必需的。在拉丁文、西里爾文和希臘文中,組合字符被用來生成字符。但是,組合字符的存在也產生了同一文本出現另一種編碼的可能性。雖然這種編碼沒有歧義性,而且也保護了數據完整性,但是處理含有組合字符的文本就更加複雜了。爲了適應那些選擇不處理組合字符的應用程序,ISO10646 定義了下列實現級別:

1) Level 1   不支持組合字符和 Hangul Jamo 字符 (一種特別的, 更加複雜的韓國文的編碼, 使用兩個或三個子字符來編碼一個韓文音節).

2) Level 2    類似於級別1, 但在某些文字中, 允許一列固定的組合字符 (例如, 希伯來文, 阿拉伯文, Devangari, 孟加拉語, 果魯穆奇語, Gujarati, Oriya, 泰米爾語, Telugo, 印.埃納德語, Malayalam, 泰國語和老撾語). 如果沒有這最起碼的幾個組合字符, UCS 就不能完整地表達這些語言.

3)Level 3    支持所有的 UCS 字符, 例如數學家可以在任意一個字符上加上一個 tilde(顎化符號,西班牙語字母上面的~)或一個箭頭(或兩者都加).

4. 編碼體系(Encoding Schemes)
標準賦予每個字符唯一的整數值,這個值稱爲代碼點(code point).如何在計算機中表示這個代碼點,就是編碼方式.
1. UCS-2
用固定的兩個字節表示一個代碼點,這兩個字節的值就等於代碼點。比如“A”的代碼點是"0x0041",其UCS-2編碼就是"0x0041". 這種編碼方式顯然不能給所有的UCS字符編碼,已經被UTF-16取代.

2. UCS-4
用固定的四個字節表示一個代碼點,這四個字節的值就等於代碼點。比如“A”的代碼點是"0x0041",其UCS-4編碼就是“0x0000 0041”.

3. UTF-8
即 UCS Transformation Format. 它是變長的編碼方式,基本規則是:
1) U+0000到U+007F之間的UCS字符采用單字節編碼0x00到0x7F,和ASCII兼容.
2) 所有大於U+007F的UCS字符采用若干個字節的編碼方法,每個字節的高位都是1,因此所有ASCII字符都不會出現在其中。
3) 多字節的第一個字節的範圍是0xC0到0xFD,這個字節前面的連續1的個數表示多少個字節出現在這個字符編碼中。它後面的字節的範圍是0x80到0xBF,也就是都是以10開頭的字節.
4) 所有(2**31)UCS字符能被編碼.
5) UTF-8編碼的字符理論上最多六個字節,16位的基本平面的字符最多3個字節.
6) 保留代碼點的字節的大端順序(Big Endian)
7) 字節0xFE,0xFF沒有被編碼,它們是保留來表示字節序(Byte Order Mark)

下表的字節序列被用了表示一個字符,使用哪個字節序列由字符的代碼點(code point)的字節數來決定.
U+00000000 – U+0000007F:
0 xxxxxxx
U+00000080 – U+000007FF:
110 xxxxx 10xxxxxx
U+00000800 – U+0000FFFF:
1110 xxxx 10xxxxxx 10xxxxxx
U+00010000 – U+001FFFFF:
11110 xxx 10xxxxxx 10xxxxxx 10xxxxxx
U+00200000 – U+03FFFFFF:
111110 xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
U+04000000 – U+7FFFFFFF:
1111110 x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx

例子:
對U+6C34(表示中文"水")進行UTF-8編碼
i. U+6C34 是  範圍U+00000800-U+0000FFFF之內,所有使用的序列是“1110xxxx 10xxxxxx 10xxxxxx”
ii. 0x6C34就是“0110 1100 0011 0100”,把這個比特序列從左到右填充到上面序列中,填充時也是從左到右,替換上面的“x”,得到
“ 11100110 10110000  10110100”,就是對於U+6C34的UTF-8編碼,寫成十六進制就是0xE6B0B4.

4. UTF-16
UTF-16也是變長編碼方式,使用一個或者兩個16位的單元來編碼. 其編碼規則是:
i) 從U+0000到U+D7FF已經從U+E000到U+FFFF之間基本平面內的字符用一個16位(就是兩個字節)的編碼,其值就等於字符的代碼點(code point).
ii)從U+10000到U+10FFFF的擴展平面內的字符,採用兩個16位的編碼單元,稱爲代理對(surrogate pairs),前一個稱爲前代理(lead surrogate),後一個稱爲後代理(trail surrogate)
  得到代理對的過程
     1)代碼點減去0x010000後得到一個20位比特的二進制序列值,這個20位比特的值將被分爲兩部分來計算前代理和後代理
     2)第一部分高位的10個比特加上0xD800得到前代理
     3)第二部分地位的10個比特加上0xDC00得到後代理
iii) 字節序上可以採用大端(以FE,FF開頭)或者小端(以FF,FE開頭)

 例子:
 對U+6C34(表示中文"水")進行UTF-16編碼
   它在基本平面內,直接使用一個16位單元編碼. UTF-16BE = 6C,34. UTF-LE = 34,6C

對U+1D22E進行UTF-16編碼
 在擴充平面內,使用兩個16位單元編碼
   1) v = 0x01D22E - 0x010000 = 0x00D22E = 1101 0010 0010 1110
   2) vh = v>>10 = 11 0100 = 0x34 
       sl = vh + 0xD800 = 0xD834
   3) vl = v & 0x3FF =  10 0010 1110 = 0x22E
       st = vl + 0xDC00 = 0xDE2E
  所以,UTF-16BE = D8,34,DE,2E
            UTF-16LE = 34,D8,2E,DE

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