原文地址: http://my.oschina.net/alphajay/blog/5691html
http://stallman.blogbus.com/logs/41709878.html程序員
Unicode是爲整合全世界的全部語言文字而誕生的。任何文字在Unicode中都對應一個值, 這個值稱爲代碼點(code point)。代碼點的值一般寫成 U+ABCD 的格式。 而文字和代碼點之間的對應關係就是UCS-2(Universal Character Set coded in 2 octets)。 顧名思義,UCS-2是用兩個字節來表示代碼點,其取值範圍爲 U+0000~U+FFFF。算法
爲了能表示更多的文字,人們又提出了UCS-4,即用四個字節表示代碼點。 它的範圍爲 U+00000000~U+7FFFFFFF,其中U+00000000~U+0000FFFF和UCS-2是同樣的。數組
要注意,UCS-2和UCS-4只規定了代碼點和文字之間的對應關係,並無規定代碼點在計算機中如何存儲。 規定存儲方式的稱爲UTF(Unicode Transformation Format),其中應用較多的就是UTF-16和UTF-8了。緩存
不難猜到,UTF-16是徹底對應於UCS-2的,即把UCS-2規定的代碼點經過Big Endian或Little Endian方式 直接保存下來。UTF-16包括三種:UTF-16,UTF-16BE(Big Endian),UTF-16LE(Little Endian)。安全
UTF-16BE和UTF-16LE不難理解,而UTF-16就須要經過在文件開頭以名爲BOM(Byte Order Mark)的字符 來代表文件是Big Endian仍是Little Endian。網絡
「ABC」這三個字符用各類方式編碼後的結果以下:less
UTF-16BE | 00 41 00 42 00 43 |
UTF-16LE | 41 00 42 00 43 00 |
UTF-16(Big Endian) | FE FF 00 41 00 42 00 43 |
UTF-16(Little Endian) | FF FE 41 00 42 00 43 00 |
UTF-16(不帶BOM) | 00 41 00 42 00 43 |
UTF-16還能表示一部分的UCS-4代碼點——U+10000~U+10FFFF。 表示算法比較複雜,簡單說明以下:編輯器
UTF-32用四個字節表示代碼點,這樣就能夠徹底表示UCS-4的全部代碼點,而無需像UTF-16那樣使用複雜的算法。 與UTF-16相似,UTF-32也包括UTF-3二、UTF-32BE、UTF-32LE三種編碼,UTF-32也一樣須要BOM字符。 僅用'ABC'舉例:ide
UTF-32BE | 00 00 00 41 00 00 00 42 00 00 00 43 |
UTF-32LE | 41 00 00 00 42 00 00 00 43 00 00 00 |
UTF-32(Big Endian) | 00 00 FE FF 00 00 00 41 00 00 00 42 00 00 00 43 |
UTF-32(Little Endian) | FF FE 00 00 41 00 00 00 42 00 00 00 43 00 00 00 |
UTF-32(不帶BOM) | 00 00 00 41 00 00 00 42 00 00 00 43 |
UTF-16和UTF-32的一個缺點就是它們固定使用兩個或四個字節, 這樣在表示純ASCII文件時會有不少00字節,形成浪費。 而RFC3629定義的UTF-8則解決了這個問題。
UTF-8用1~4個字節來表示代碼點。表示方式以下:
UCS-2 (UCS-4) | 位序列 | 第一字節 | 第二字節 | 第三字節 | 第四字節 |
U+0000 .. U+007F | 00000000-0xxxxxxx | 0xxxxxxx | |
|
|
U+0080 .. U+07FF | 00000xxx-xxyyyyyy | 110xxxxx | 10yyyyyy | |
|
U+0800 .. U+FFFF | xxxxyyyy-yyzzzzzz | 1110xxxx | 10yyyyyy | 10zzzzzz | |
U+10000..U+1FFFFF | 00000000-000wwwxx- xxxxyyyy-yyzzzzzzz |
11110www | 10xxxxxx | 10yyyyyy | 10zzzzzz |
* 0xxxxxxx (00-7f)
* 110xxxxx 10xxxxxx (c0-df)(80-bf)
* 1110xxxx 10xxxxxx 10xxxxxx (e0-ef)(80-bf)(80-bf)
* 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx (f0-f7)(80-bf)(80-bf)(80-bf)
* 111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx (f8-fb)(80-bf)(80-bf)(80-bf)(80-bf)
* 1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx (fc-fd)(80-bf)(80-bf)(80-bf)(80-bf)(80-bf)
可見,ASCII字符(U+0000~U+007F)部分徹底使用一個字節,避免了存儲空間的浪費。 並且UTF-8再也不須要BOM字節。
另外,從上表中能夠看出,單字節編碼的第一字節爲[00-7F],雙字節編碼的第一字節爲[C0-DF], 三字節編碼的第一字節爲[E0-EF]。這樣只要看到第一個字節的範圍就能夠知道編碼的字節數。 這樣也能夠大大簡化算法。
前面提到從ASCII、GB23十二、GBK到GB18030的編碼方法是向下兼容的。而Unicode只與ASCII兼容(更準確地說,是與 ISO-8859-1兼容),與GB碼不兼容。例如「漢」字的Unicode編碼是6C49,而GB碼是BABA。
Unicode也是一種字符編碼方法,不過它是由國際組織設計,能夠容納全世界全部語言文字的編碼方案。Unicode的學名 是"Universal Multiple-Octet Coded Character Set",簡稱爲UCS。UCS能夠看做是"Unicode Character Set"的縮寫。
根據維基百科全書(http://zh.wikipedia.org/wiki/)的記載:歷史上存在兩個試圖獨立設計Unicode的組織,即國 際標準化組織(ISO)和一個軟件製造商的協會(unicode.org)。ISO開發了ISO 10646項目,Unicode協會開發了Unicode項目。
在1991年先後,雙方都認識到世界不須要兩個不兼容的字符集。因而它們開始合併雙方的工做成果,併爲創立一個單一編碼表而協同工做。從 Unicode2.0開始,Unicode項目採用了與ISO 10646-1相同的字庫和字碼。
目前兩個項目仍都存在,並獨立地公佈各自的標準。Unicode協會如今的最新版本是2005年的Unicode 4.1.0。ISO的最新標準是ISO 10646-3:2003。
UCS只是規定如何編碼,並無規定如何傳輸、保存這個編碼。 例如「漢」字的UCS編碼是6C49,我能夠用4個ascii數字來傳輸、保存這個編 碼;也能夠用utf-8編碼:3個連續的字節E6 B1 89來表示它。關鍵在於通訊雙方都要承認。UTF-八、UTF-七、UTF-16都是被普遍接受的方案。UTF-8的一個特別的好處是它與ISO- 8859-1徹底兼容。UTF是「UCS Transformation Format」的縮寫。
IETF的RFC2781和RFC3629以RFC的一向風格,清晰、明快又不失嚴謹地描述了UTF-16和UTF-8的編碼方法。我老是記不得 IETF是Internet Engineering Task Force的縮寫。但IETF負責維護的RFC是Internet上一切規範的基礎。
目前Windows的內核已經支持Unicode字符集,這樣在內核上能夠支持全世界全部的語言文字。可是因爲現有的大量程序和文檔都採用了某種特 定語言的編碼,例如GBK,Windows不可能不支持現有的編碼,而所有改用Unicode。
Windows使用代碼頁(code page)來適應各個國家和地區。code page能夠被理解爲前面提到的內碼。GBK對應的code page是CP936。
微軟也爲GB18030定義了code page:CP54936。可是因爲GB18030有一部分4字節編碼,而Windows的代碼頁只支持單字節和雙字節編碼,因此這個code page是沒法真正使用的。
UCS有兩種格式:UCS-2和UCS-4。顧名思義,UCS-2就是用兩個字節編碼,UCS-4就是用4個字節(實際上只用了31位,最高位必須 爲0)編碼。下面讓咱們作一些簡單的數學遊戲:
UCS-2有2^16=65536個碼位,UCS-4有2^31=2147483648個碼位。
UCS-4根據最高位爲0的最高字節分紅2^7=128個 group。每一個group再根據次高字節分爲256個plane。每一個plane根據第 3個字節分爲256行 (rows),每行包含256個cells。固然同一行的cells只是最後一個字節不一樣,其他都相同。
group 0的plane 0被稱做Basic Multilingual Plane, 即BMP。或者說UCS-4中,高兩個字節爲0的碼位被稱做BMP。
將UCS-4的BMP去掉前面的兩個零字節就獲得了UCS-2。在UCS-2的兩個字節前加上兩個零字節,就獲得了UCS-4的BMP。而目前的 UCS-4規範中尚未任何字符被分配在BMP以外。
UTF-8就是以8位爲單元對UCS進行編碼。從UCS-2到UTF-8的編碼方式以下:
UCS-2編碼(16進制) | UTF-8 字節流(二進制) |
0000 - 007F | 0xxxxxxx |
0080 - 07FF | 110xxxxx 10xxxxxx |
0800 - FFFF | 1110xxxx 10xxxxxx 10xxxxxx |
例如「漢」字的Unicode編碼是6C49。6C49在0800-FFFF之間,因此確定要用3字節模板了:1110xxxx 10xxxxxx 10xxxxxx。將6C49寫成二進制是:0110 110001 001001, 用這個比特流依次代替模板中的x,獲得:11100110 10110001 10001001,即 E6 B1 89。
讀者能夠用記事本測試一下咱們的編碼是否正確。須要注意,UltraEdit在打開utf-8編碼的文本文件時會自動轉換爲UTF-16,可能產生 混淆。你能夠在設置中關掉這個選項。更好的工具是Hex Workshop。
UTF-16以16位爲單元對UCS進行編碼。對於小於0x10000的UCS碼,UTF-16編碼就等於UCS碼對應的16位無符號整數。對於不 小於0x10000的UCS碼,定義了一個算法。不過因爲實際使用的UCS2,或者UCS4的BMP必然小於0x10000,因此就目前而言,能夠認爲 UTF-16和UCS-2基本相同。但UCS-2只是一個編碼方案,UTF-16卻要用於實際的傳輸,因此就不得不考慮字節序的問題。
這是一篇程序員寫給程序員的趣味讀物。所謂趣味是指能夠比較輕鬆地瞭解一些原來不清楚的概念,增進知識,相似於打RPG遊戲的升級。整理這篇文章的 動機是兩個問題:
使用Windows記事本的「另存爲」,能夠在GBK、Unicode、Unicode big endian和UTF-8這幾種編碼方式間相互轉換。一樣是txt文件,Windows是怎樣識別編碼方式的呢?
我很早前就發現Unicode、Unicode big endian和UTF-8編碼的txt文件的開頭會多出幾個字節,分別是FF、FE(Unicode),FE、FF(Unicode big endian),EF、BB、BF(UTF-8)。但這些標記是基於什麼標準呢?
查了查相關資料,總算將這些問題弄清楚了,順帶也瞭解了一些Unicode的細節。寫成一篇文章,送給有過相似疑問的朋友。本文在寫做時儘可能作到通 俗易懂,但要求讀者知道什麼是字節,什麼是十六進制。
big endian和little endian是CPU處理多字節數的不一樣方式。例如「漢」字的Unicode編碼是6C49。那麼寫到文件裏時,到底是將6C寫在前面,仍是將49寫在前 面?若是將6C寫在前面,就是big endian。若是將49寫在前面,就是little endian。
「endian」這個詞出自《格列佛遊記》。小人國的內戰就源於吃雞蛋時是究竟從大頭(Big-Endian)敲開仍是從小頭(Little- Endian)敲開,由此曾發生過六次叛亂,一個皇帝送了命,另外一個丟了王位。
咱們通常將endian翻譯成「字節序」,將big endian和little endian稱做「大尾」和「小尾」。
字符必須編碼後才能被計算機處理。計算機使用的缺省編碼方式就是計算機的內碼。早期的計算機使用7位的ASCII編碼,爲了處理漢字,程序員設計了 用於簡體中文的GB2312和用於繁體中文的big5。
GB2312(1980年)一共收錄了7445個字符,包括6763個漢字和682個其它符號。漢字區的內碼範圍高字節從B0-F7,低字節從 A1-FE,佔用的碼位是72*94=6768。其中有5個空位是D7FA-D7FE。
GB2312支持的漢字太少。1995年的漢字擴展規範GBK1.0收錄了21886個符號,它分爲漢字區和圖形符號區。漢字區包括21003個字 符。
從ASCII、GB2312到GBK,這些編碼方法是向下兼容的,即同一個字符在這些方案中老是有相同的編碼,後面的標準支持更多的字符。在這些 編 碼中,英文和中文能夠統一地處理。區分中文編碼的方法是高字節的最高位不爲0。按照程序員的稱呼,GB23十二、GBK都屬於雙字節字符集 (DBCS)。
2000年的GB18030是取代GBK1.0的正式國家標準。該標準收錄了27484個漢字,同時還收錄了藏文、蒙文、維吾爾文等主要的少數民 族 文字。從漢字字彙上說,GB18030在GB13000.1的20902個漢字的基礎上增長了CJK擴展A的6582個漢字(Unicode碼 0x3400-0x4db5),一共收錄了27484個漢字。
CJK就是中日韓的意思。Unicode爲了節省碼位,將中日韓三國語言中的文字統一編碼。GB13000.1就是ISO/IEC 10646-1的中文版,至關於Unicode 1.1。
GB18030的編碼採用單字節、雙字節和4字節方案。其中單字節、雙字節和GBK是徹底兼容的。4字節編碼的碼位就是收錄了CJK擴展A的 6582個漢字。 例如:UCS的0x3400在GB18030中的編碼應該是8139EF30,UCS的0x3401在GB18030中的編碼應該是8139EF31。
微軟提供了GB18030的升級包,但這個升級包只是提供了一套支持CJK擴展A的6582個漢字的新字體:新宋體-18030,並不改變內碼。 Windows 的內碼仍然是GBK。
這裏還有一些細節:
GB2312的原文仍是區位碼,從區位碼到內碼,須要在高字節和低字節上分別加上A0。
對於任何字符編碼,編碼單元的順序是由編碼方案指定的,與endian無關。例如GBK的編碼單元是字節,用兩個字節表示一個漢字。 這兩個字節的順序是固定的,不受CPU字節序的影響。UTF-16的編碼單元是word(雙字節),word之間的順序是編碼方案指定的,word內部的 字節排列纔會受到endian的影響。後面還會介紹UTF-16。
GB2312的兩個字節的最高位都是1。但符合這個條件的碼位只有128*128=16384個。因此GBK和GB18030的低字節最高位 均可能 不是1。不過這不影響DBCS字符流的解析:在讀取DBCS字符流時,只要遇到高位爲1的字節,就能夠將下兩個字節做爲一個雙字節編碼,而不用管低字節的 高位是什麼。
前面提到從ASCII、GB23十二、GBK到GB18030的編碼方法是向下兼容的。而Unicode只與ASCII兼容(更準確地說,是與 ISO-8859-1兼容),與GB碼不兼容。例如「漢」字的Unicode編碼是6C49,而GB碼是BABA。
Unicode也是一種字符編碼方法,不過它是由國際組織設計,能夠容納全世界全部語言文字的編碼方案。Unicode的學名 是"Universal Multiple-Octet Coded Character Set",簡稱爲UCS。UCS能夠看做是"Unicode Character Set"的縮寫。
根據維基百科全書(http://zh.wikipedia.org/wiki/)的記載:歷史上存在兩個試圖獨立設計Unicode的組織,即 國 際標準化組織(ISO)和一個軟件製造商的協會(unicode.org)。ISO開發了ISO 10646項目,Unicode協會開發了Unicode項目。
在1991年先後,雙方都認識到世界不須要兩個不兼容的字符集。因而它們開始合併雙方的工做成果,併爲創立一個單一編碼表而協同工做。從 Unicode2.0開始,Unicode項目採用了與ISO 10646-1相同的字庫和字碼。
目前兩個項目仍都存在,並獨立地公佈各自的標準。Unicode協會如今的最新版本是2005年的Unicode 4.1.0。ISO的最新標準是ISO 10646-3:2003。
UCS只是規定如何編碼,並無規定如何傳輸、保存這個編碼。例如「漢」字的UCS編碼是6C49,我能夠用4個ascii數字來傳輸、保存這個 編 碼;也能夠用utf-8編碼:3個連續的字節E6 B1 89來表示它。關鍵在於通訊雙方都要承認。UTF-八、UTF-七、UTF-16都是被普遍接受的方案。UTF-8的一個特別的好處是它與ISO- 8859-1徹底兼容。UTF是「UCS Transformation Format」的縮寫。
IETF的RFC2781和RFC3629以RFC的一向風格,清晰、明快又不失嚴謹地描述了UTF-16和UTF-8的編碼方法。我老是記不得 IETF是Internet Engineering Task Force的縮寫。但IETF負責維護的RFC是Internet上一切規範的基礎。
目前Windows的內核已經支持Unicode字符集,這樣在內核上能夠支持全世界全部的語言文字。可是因爲現有的大量程序和文檔都採用了某種特 定語言的編碼,例如GBK,Windows不可能不支持現有的編碼,而所有改用Unicode。
Windows使用代碼頁(code page)來適應各個國家和地區。code page能夠被理解爲前面提到的內碼。GBK對應的code page是CP936。
微軟也爲GB18030定義了code page:CP54936。可是因爲GB18030有一部分4字節編碼,而Windows的代碼頁只支持單字節和雙字節編碼,因此這個code page是沒法真正使用的。
UCS有兩種格式:UCS-2和UCS-4。顧名思義,UCS-2就是用兩個字節編碼,UCS-4就是用4個字節(實際上只用了31位,最高位必須 爲0)編碼。下面讓咱們作一些簡單的數學遊戲:
UCS-2有2^16=65536個碼位,UCS-4有2^31=2147483648個碼位。
UCS-4根據最高位爲0的最高字節分紅2^7=128個group。每一個group再根據次高字節分爲256個plane。每一個plane根據 第 3個字節分爲256行 (rows),每行包含256個cells。固然同一行的cells只是最後一個字節不一樣,其他都相同。
group 0的plane 0被稱做Basic Multilingual Plane, 即BMP。或者說UCS-4中,高兩個字節爲0的碼位被稱做BMP。
將UCS-4的BMP去掉前面的兩個零字節就獲得了UCS-2。在UCS-2的兩個字節前加上兩個零字節,就獲得了UCS-4的BMP。而目前的 UCS-4規範中尚未任何字符被分配在BMP以外。
UTF-8就是以8位爲單元對UCS進行編碼。從UCS-2到UTF-8的編碼方式以下:
UCS-2編碼(16進制) | UTF-8 字節流(二進制) |
0000 - 007F | 0xxxxxxx |
0080 - 07FF | 110xxxxx 10xxxxxx |
0800 - FFFF | 1110xxxx 10xxxxxx 10xxxxxx |
例如「漢」字的Unicode編碼是6C49。6C49在0800-FFFF之間,因此確定要用3字節模板了:1110xxxx 10xxxxxx 10xxxxxx。將6C49寫成二進制是:0110 110001 001001, 用這個比特流依次代替模板中的x,獲得:11100110 10110001 10001001,即 E6 B1 89。
讀者能夠用記事本測試一下咱們的編碼是否正確。須要注意,UltraEdit在打開utf-8編碼的文本文件時會自動轉換爲UTF-16,可能產生 混淆。你能夠在設置中關掉這個選項。更好的工具是Hex Workshop。
UTF-16以16位爲單元對UCS進行編碼。對於小於0x10000的UCS碼,UTF-16編碼就等於UCS碼對應的16位無符號整數。對於 不 小於0x10000的UCS碼,定義了一個算法。不過因爲實際使用的UCS2,或者UCS4的BMP必然小於0x10000,因此就目前而言,能夠認爲 UTF-16和UCS-2基本相同。但UCS-2只是一個編碼方案,UTF-16卻要用於實際的傳輸,因此就不得不考慮字節序的問題。
UTF-8以字節爲編碼單元,沒有字節序的問題。UTF-16以兩個字節爲編碼單元,在解釋一個UTF-16文本前,首先要弄清楚每一個編碼單元的字 節序。例如「奎」的Unicode編碼是594E,「乙」的Unicode編碼是4E59。若是咱們收到UTF-16字節流「594E」,那麼這是「奎」 仍是「乙」?
Unicode規範中推薦的標記字節順序的方法是BOM。BOM不是「Bill Of Material」的BOM表,而是Byte Order Mark。BOM是一個有點小聰明的想法:
在UCS編碼中有一個叫作"ZERO WIDTH NO-BREAK SPACE"的字符,它的編碼是FEFF。而FFFE在UCS中是不存在的字符,因此不該該出如今實際傳輸中。UCS規範建議咱們在傳輸字節流前,先傳輸 字符"ZERO WIDTH NO-BREAK SPACE"。
這樣若是接收者收到FEFF,就代表這個字節流是Big-Endian的;若是收到FFFE,就代表這個字節流是Little-Endian的。因 此字符"ZERO WIDTH NO-BREAK SPACE"又被稱做BOM。
UTF-8不須要BOM來代表字節順序,但能夠用BOM來代表編碼方式。字符"ZERO WIDTH NO-BREAK SPACE"的UTF-8編碼是EF BB BF(讀者能夠用咱們前面介紹的編碼方法驗證一下)。因此若是接收者收到以EF BB BF開頭的字節流,就知道這是UTF-8編碼了。
Windows就是使用BOM來標記文本文件的編碼方式的。
「GB2312的原文」是指國家1980年的一個標準《中華人民共和國國家標準 信息交換用漢字編碼字符集 基本集 GB 2312-80》。這個標準用兩個數來編碼漢字和中文符號。第一個數稱爲「區」,第二個數稱爲「位」。因此也稱爲區位碼。1-9區是中文符號,16-55 區是一級漢字,56-87區是二級漢字。如今Windows也還有區位輸入法,例如輸入1601獲得「啊」。(這個區位輸入法能夠自動識別16進制的 GB2312和10進制的區位碼,也就是說輸入B0A1一樣會獲得「啊」。)
內碼是指操做系統內部的字符編碼。早期操做系統的內碼是與語言相關的。如今的Windows在系統內部支持Unicode,而後用代碼頁適應各類語 言,「內碼」的概念就比較模糊了。微軟通常將缺省代碼頁指定的編碼說成是內碼。
內碼這個詞彙,並無什麼官方的定義,代碼頁也只是微軟這個公司的叫法。做爲程序員,咱們只要知道它們是什麼東西,沒有必要過多地考證這些名詞。
Windows中有缺省代碼頁的概念,即缺省用什麼編碼來解釋字符。例如Windows的記事本打開了一個文本文件,裏面的內容是字節流:BA、 BA、D七、D6。Windows應該去怎麼解釋它呢?
是按照Unicode編碼解釋、仍是按照GBK解釋、仍是按照BIG5解釋,仍是按照ISO8859-1去解釋?若是按GBK去解釋,就會獲得 「漢 字」兩個字。按照其它編碼解釋,可能找不到對應的字符,也可能找到錯誤的字符。所謂「錯誤」是指與文本做者的本意不符,這時就產生了亂碼。
答案是Windows按照當前的缺省代碼頁去解釋文本文件裏的字節流。缺省代碼頁能夠經過控制面板的區域選項設置。記事本的另存爲中有一項 ANSI,其實就是按照缺省代碼頁的編碼方法保存。
Windows的內碼是Unicode,它在技術上能夠同時支持多個代碼頁。只要文件能說明本身使用什麼編碼,用戶又安裝了對應的代碼 頁,Windows就能正確顯示,例如在HTML文件中就能夠指定charset。
有的HTML文件做者,特別是英文做者,認爲世界上全部人都使用英文,在文件中不指定charset。若是他使用了0x80-0xff之間的字符, 中文Windows又按照缺省的GBK去解釋,就會出現亂碼。這時只要在這個html文件中加上指定charset的語句,例如:
<meta http-equiv="Content-Type" content="text/html; charset=ISO8859-1">
如 果原做者使用的代碼頁和ISO8859-1兼容,就不會出現亂碼了。
再說區位碼,啊的區位碼是1601,寫成16進制是0x10,0x01。這和計算機普遍使用的ASCII編碼衝突。爲了兼容00-7f的 ASCII 編碼,咱們在區位碼的高、低字節上分別加上A0。這樣「啊」的編碼就成爲B0A1。咱們將加過兩個A0的編碼也稱爲GB2312編碼,雖然GB2312的 原文根本沒提到這一點。
*****************************************************************************
Unicode字符集和多字節字符集關係
在計算機中字符一般並非保存爲圖像,每一個字符都是使用一個編碼來表示的,而每一個字符究竟使用哪一個編碼表明,要取決於使用哪一個字符集(charset)。
在 最初的時候,Internet上只有一種字符集——ANSI的ASCII字符集,它使用7 bits來表示一個字符,總共表示128個字符,其中包括了英文字母、數字、標點符號等經常使用字符。以後,又進行擴展,使用8 bits表示一個字符,能夠表示256個字符,主要在原來的7 bits字符集的基礎上加入了一些特殊符號例如製表符。
後來,因爲各國語言的加入,ASCII已經不能知足信息交流的須要,所以,爲了可以表示其它國家的文字,各國在ASCII的基礎上制定了本身的字符集,這些從ANSI標準派生的字符集被習慣的統稱爲ANSI字符集,它們正式的名稱應該是MBCS(Multi-Byte Chactacter System,即多字節字符系統)。這些派生字符集的特色是以ASCII 127 bits爲基礎,兼容ASCII 127,他們使用大於128的編碼做爲一個Leading Byte,緊跟在Leading Byte後的第二(甚至第三)個字符與Leading Byte一塊兒做爲實際的編碼。這樣的字符集有不少,咱們常見的GB-2312就是其中之一。
例 如在GB-2312字符集中,「連通」的編碼爲C1 AC CD A8,其中C1和CD就是Leading Byte。前127個編碼爲標準ASCII保留,例如「0」的編碼是30H(30H表示十六進制的30)。軟件在讀取時,若是看到30H,知道它小於 128就是標準ASCII,表示「0」,看到C1大於128就知道它後面有一個另外的編碼,所以C1 AC一同構成一個整個的編碼,在GB-2312字符集中表示「連」。
因爲每種語言都制定了本身的字符集,致使最後存在的各類字符集實在太多,在國際交流中要常常轉換字符集很是不便。所以,提出了Unicode字符集,它固定使用16 bits(兩個字節、一個字)來表示一個字符,共能夠表示65536個字符。將世界上幾乎全部語言的經常使用字符收錄其中,方便了信息交流。標準的Unicode稱爲UTF-16。後來爲了雙字節的Unicode可以在現存的處理單字節的系統上正確傳輸,出現了UTF-8,使用相似MBCS的方式對Unicode進行編碼。注意UTF-8是編碼,它屬於Unicode字符集。 Unicode字符集有多種編碼形式,而ASCII只有一種,大多數MBCS(包括GB-2312)也只有一種。Unicode的最初目標,是用1個16 位的編碼來爲超過65000字符提供映射。但這還不夠,它不能覆蓋所有歷史上的文字,也不能解決傳輸的問題 (implantation head-ache's),尤爲在那些基於網絡的應用中。已有的軟件必須作大量的工做來程序16位的數據。所以,Unicode用一些基本的保留字符制定了三套編碼方式。它們分別是UTF-8,UTF-16和UTF-32。 正如名字所示,在UTF-8中,字符是以8位序列來編碼的,用一個或幾個字節來表示一個字符。這種方式的最大好處,是UTF-8保留了ASCII字符的編 碼作爲它的一部分,例如,在UTF-8和ASCII中,「A」的編碼都是0x41.UTF-16和UTF-32分別是Unicode的16位和32位編碼 方式。考慮到最初的目的,一般說的Unicode就是指UTF-16。
例如「連通」兩個字的Unicode標準編碼UTF-16 (big endian)爲:DE 8F 1A 90
而其UTF-8編碼爲:E8 BF 9E E9 80 9A
最後,當一個軟件打開一個文本時,它要作的第一件事是決定這個文本到底是使用哪一種字符集的哪一種編碼保存的。軟件有三種途徑來決定文本的字符集和編碼:
最標準的途徑是檢測文本最開頭的幾個字節,以下表:
開頭字節 Charset/encoding
EF BB BF UTF-8
FE FF UTF-16/UCS-2, little endian
FF FE UTF-16/UCS-2, big endian
FF FE 00 00 UTF-32/UCS-4, little endian.
00 00 FE FF UTF-32/UCS-4, big-endian.例如插入標記後,連通」兩個字的UTF-16 (big endian)和UTF-8碼分別爲:
FF FE DE 8F 1A 90
EF BB BF E8 BF 9E E9 80 9A
但 是MBCS文本沒有這些位於開頭的字符集標記,更不幸的是,一些早期的和一些設計不良的軟件在保存Unicode文本時不插入這些位於開頭的字符集標記。 所以,軟件不能依賴於這種途徑。這時,軟件能夠採起一種比較安全的方式來決定字符集及其編碼,那就是彈出一個對話框來請示用戶,例如將那個「連通」文件拖 到MS Word中,Word就會彈出一個對話框。
若是軟件不想麻煩用戶,或者它不方便向用戶請示,那它只能採起本身「猜」的方法,軟件能夠根據整個文本的特徵來猜想它可能屬於哪一個charset,這就極可能不許了。使用記事本打開那個「連通」文件就屬於這種狀況。
我 們能夠證實這一點:在記事本中鍵入「連通」後,選擇「Save As」,會看到最後一個下拉框中顯示有「ANSI」,這時保存。當再當打開「連通」文件出現亂碼後,再點擊「File」->「Save As」,會看到最後一個下拉框中顯示有「UTF-8」,這說明記事本認爲當前打開的這個文本是一個UTF-8編碼的文本。而咱們剛纔保存時是用ANSI字 符集保存的。這說明,記事本猜想了「連通」文件的字符集,認爲它更像一個UTF-8編碼文本。這是由於「連通」兩個字的GB-2312編碼看起來更像 UTF-8編碼致使的,這是一個巧合,不是全部文字都這樣。可使用記事本的打開功能,在打開「連通」文件時在最後一個下拉框中選擇ANSI,就能正常顯 示了。反過來,若是以前保存時保存爲UTF-8編碼,則直接打開也不會出現問題。
若是將「連通」文件放入MS Word中,Word也會認爲它是一個UTF-8編碼的文件,但它不能肯定,所以會彈出一個對話框詢問用戶,這時選擇「簡體中文(GB2312)」,就能正常打開了。記事本在這一點上作得比較簡化罷了,這與這個程序的定位是一致的。
須要提醒你們的是,部分Windows 2000字型沒法顯示全部的Unicode字符。若是發現文件中缺乏了某些字符,只需將其變動爲其它字型便可。
big endian和little endian
big endian和little endian是CPU處理多字節數的不一樣方式。例如「漢」字的Unicode編碼是6C49。那麼寫到文件裏時,到底是將6C寫在前面,仍是將49寫在前面?若是將6C寫在前面,就是big endian。仍是將49寫在前面,就是little endian。
「endian」這個詞出自《格列佛遊記》。小人國的內戰就源於吃雞蛋時是究竟從大頭(Big-Endian)敲開仍是從小頭(Little-Endian)敲開,由此曾發生過六次叛亂,其中一個皇帝送了命,另外一個丟了王位。
咱們通常將endian翻譯成「字節序」,將big endian和little endian稱做「大尾」和「小尾」。
Unicode big endian:在Big-endian處理器(如蘋果Macintosh電腦)上創建的Unicode文件中的文字位元組(存放單位)排列順序,與在 Intel處理器上創建的文件的文字位元組排列順序相反。最重要的位元組擁有最低的地址,且會先儲存文字中較大的一端。爲使這類電腦的用戶可以存取你的文 件,可選擇Unicode big-endian格式。
#####################################################################
ANSI字符,UNICODE,寬字符,窄字符,多字節字符集
Unicode :寬字節字符集
1. 如何取得一個既包含單字節字符又包含雙字節字符的字符串的字符個數?
能夠調用Microsoft Visual C++的運行期庫包含函數_mbslen來操做多字節(既包括單字節也包括雙字節)字符串。
調用strlen函數,沒法真正瞭解字符串中究竟有多少字符,它只能告訴你到達結尾的0以前有多少個字節。
2. 如何對DBCS(雙字節字符集)字符串進行操做?
函數 描述
PTSTR CharNext ( LPCTSTR ); 返回字符串中下一個字符的地址
PTSTR CharPrev ( LPCTSTR, LPCTSTR ); 返回字符串中上一個字符的地址
BOOL IsDBCSLeadByte( BYTE ); 若是該字節是DBCS字符的第一個字節,則返回非0值
3. 爲何要使用Unicode?
(1) 能夠很容易地在不一樣語言之間進行數據交換。
(2) 使你可以分配支持全部語言的單個二進制.exe文件或DLL文件。
(3) 提升應用程序的運行效率。
Windows 2000是使用Unicode從頭進行開發的,若是調用任何一個Windows函數並給它傳遞一個ANSI字符串,那麼系統首先要將字符串轉換成 Unicode,而後將Unicode字符串傳遞給操做系統。若是但願函數返回ANSI字符串,系統就會首先將Unicode字符串轉換成ANSI字符 串,而後將結果返回給你的應用程序。進行這些字符串的轉換須要佔用系統的時間和內存。經過從頭開始用Unicode來開發應用程序,就可以使你的應用程序 更加有效地運行。
Windows CE 自己就是使用Unicode的一種操做系統,徹底不支持ANSI Windows函數
Windows 98 只支持ANSI,只能爲ANSI開發應用程序。
Microsoft公司將COM從16位Windows轉換成Win32時,公司決定須要字符串的全部COM接口方法都只能接受Unicode字符串。
4. 如何編寫Unicode源代碼?
Microsoft公司爲Unicode設計了WindowsAPI,這樣,能夠儘可能減小代碼的影響。實際上,能夠編寫單個源代碼文件,以便使用或者不使用Unicode來對它進行編譯。只須要定義兩個宏(UNICODE和_UNICODE),就能夠修改而後從新編譯該源文件。
_UNICODE宏用於C運行期頭文件,而UNICODE宏則用於Windows頭文件。當編譯源代碼模塊時,一般必須同時定義這兩個宏。
5. Windows定義的Unicode數據類型有哪些?
數據類型 說明
WCHAR Unicode字符
PWSTR 指向Unicode字符串的指針
PCWSTR 指向一個恆定的Unicode字符串的指針
對應的ANSI數據類型爲CHAR,LPSTR和LPCSTR。
ANSI/Unicode通用數據類型爲TCHAR,PTSTR,LPCTSTR。
6. 如何對Unicode進行操做?
字符集 特性 實例
ANSI 操做函數以str開頭 strcpy
Unicode 操做函數以wcs開頭 wcscpy
MBCS 操做函數以_mbs開頭 _mbscpy
ANSI/Unicode 操做函數以_tcs開頭 _tcscpy(C運行期庫)
ANSI/Unicode 操做函數以lstr開頭 lstrcpy(Windows函數)
全部新的和未過期的函數在Windows2000中都同時擁有ANSI和Unicode兩個版本。ANSI版本函數結尾以A表示;Unicode版本函數結尾以W表示。Windows會以下定義:
#ifdef UNICODE
#define CreateWindowEx CreateWindowExW
#else
#define CreateWindowEx CreateWindowExA
#endif // !UNICODE
7. 如何表示Unicode字符串常量?
字符集 實例
ANSI 「string」
Unicode L「string」
ANSI/Unicode T(「string」)或_TEXT(「string」)if( szError[0] == _TEXT(‘J’) ){ }
8. 爲何應當儘可能使用操做系統函數?
這將有助於稍稍提升應用程序的運行性能,由於操做系統字符串函數經常被大型應用程序好比操做系統的外殼進程Explorer.exe所使用。因爲這些函數使用得不少,所以,在應用程序運行時,它們可能已經被裝入RAM。
如:StrCat,StrChr,StrCmp和StrCpy等。
9. 如何編寫符合ANSI和Unicode的應用程序?
(1) 將文本串視爲字符數組,而不是chars數組或字節數組。
(2) 將通用數據類型(如TCHAR和PTSTR)用於文本字符和字符串。
(3) 將顯式數據類型(如BYTE和PBYTE)用於字節、字節指針和數據緩存。
(4) 將TEXT宏用於原義字符和字符串。
(5) 執行全局性替換(例如用PTSTR替換PSTR)。
(6) 修改字符串運算問題。例如函數一般但願在字符中傳遞一個緩存的大小,而不是字節。這 意味着不該該傳遞sizeof(szBuffer),而應該傳遞(sizeof(szBuffer)/sizeof(TCHAR)。另外,若是須要爲字符 串分配一個內存塊,而且擁有該字符串中的字符數目,那麼請記住要按字節來分配內存。這就是說,應該調用malloc(nCharacters *sizeof(TCHAR)),而不是調用malloc(nCharacters)。
10. 如何對字符串進行有選擇的比較?
經過調用CompareString來實現。
標誌 含義
NORM_IGNORECASE 忽略字母的大小寫
NORM_IGNOREKANATYPE 不區分平假名與片假名字符
NORM_IGNORENONSPACE 忽略無間隔字符
NORM_IGNORESYMBOLS 忽略符號
NORM_IGNOREWIDTH 不區分單字節字符與做爲雙字節字符的同一個字符
SORT_STRINGSORT 將標點符號做爲普通符號來處理
11. 如何判斷一個文本文件是ANSI仍是Unicode?
判斷若是文本文件的開頭兩個字節是0xFF和0xFE,那麼就是Unicode,不然是ANSI。
12. 如何判斷一段字符串是ANSI仍是Unicode?
用IsTextUnicode進行判斷。IsTextUnicode使用一系列統計方法和定性方法,以便猜想緩存的內容。因爲這不是一種確切的科學方法,所以 IsTextUnicode有可能返回不正確的結果。
13. 如何在Unicode與ANSI之間轉換字符串?
Windows函數MultiByteToWideChar用於將多字節字符串轉換成寬字符串;函數WideCharToMultiByte將寬字符串轉換成等價的多字節字符串。
________________________________________________________________
UCS,UNICODE和UTF-8
UCS,UNICODE和UTF-8
本文簡單介紹UCS,UNICODE和UTF-8,並利用C語言實現了UTF-8與UCS2之間的互相轉化。
1.什麼是UCS和ISO10646?
國 際標準ISO10646定義了通用字符集(Universal Character Set, UCS). UCS是全部其它字符集標準的一個超集,它保證也其它字符集雙向兼容,即編碼間相互轉換不會丟失任何信息。UCS字符集U+0000到U+007F與 US-ASCII是一致的。
2.什麼是UNICODE
歷史上, 有兩個獨立的, 創立單一字符集的嘗試. 一個是國際標準化組織(ISO)的 ISO 10646 項目, 另外一個是由(一開始大可能是美國的)多語言軟件製造商組成的協會組織的 Unicode 項目. 幸運的是, 1991年先後, 兩個項目的參與者都認識到, 世界不 須要兩個不一樣的單一字符集. 它們合併雙方的工做成果, 併爲創立一個單一編碼表而協同工做. 兩個項目仍都存在並獨立地公佈各自的標準, 但 Unicode 協會和 ISO/IEC JTC1/SC2 都贊成保持 Unicode 和 ISO 10646 標準的碼錶兼容, 並緊密地共同調整任何將來的擴展.
3.什麼是UTF-8(一種傳送和存儲格式)
UCS和UNICODE爲每一個字符分配了一個對應的整數,但並無明確說明其實現機制.故存在多種編碼方式,其中以兩個字節和四個字節來存儲一個字符的方法分別叫UCS-2, UCS-4,要將一個ASCII文件轉換成一個UCS-2文件只要在每一個字節前加一個字節0X00,轉換成UCS-4只要在每一個字節前加三個0X00。
而internet上大量的信息是以ASCII碼存在的,若是都用兩個字節來存儲將浪費大量的資源,同時Unix和Linux下使用USC-2和USC-4會致使嚴重問題,因而出現了UTF-8(定義於ISO10646-1).
UTF-8
(UTF-8 stands for Unicode Transformation Format-8. It is an octet (8-bit) lossless encoding of Unicode characters.)
UNICODE(UCS)和UTF-8的對應關係。
U-00000000 - U-0000007F: 0xxxxxxx (ASCII碼 最重用)
U-00000080 - U-000007FF: 110xxxxx 10xxxxxx (第二優先級經常使用)
U-00000800 - U-0000FFFF: 1110xxxx 10xxxxxx 10xxxxxx
U-00010000 - U-001FFFFF: 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
U-00200000 - U-03FFFFFF: 111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
U-04000000 - U-7FFFFFFF: 1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx (不多用)
在多字節串中,第一個字節的開頭‘1’的數目就是整個串中字節的數目.
下面舉UCS-2與UTF-8的對應關係,並利用C語言實現之間的互相轉化。
-----------------------------------------------------------------------------------------------------------
| UCS2 | UTF-8 |
|----------------------------------------------------------------------------------------------------------
| | code | 1st Byte | 2nd byte | 3rd Byte |
|--------------------------------------------------------------------------------------------------------
| 000000000aaaaaaa | 0000 - 007F | 0aaaaaaa | | |
|--------------------------------------------------------------------------------------------------------
| 00000bbbbbaaaaaa | 0080 - 07FF | 110bbbbb | 10aaaaaa | |
|--------------------------------------------------------------------------------------------------------
| ccccbbbbbbaaaaaa | 0800 - FFFF | 1110cccc | 10bbbbbb | 10aaaaaa |
|--------------------------------------------------------------------------------------------------------
alphajay的疑問: 這裏是a b c應該是從0 1中取的一個bit位吧
由於USC-2 每一個字符用兩個字節 16bit表示
在這兒我只實現了單個字符的轉換,串的轉換也是同樣的道理。
1,把一個UTF-8字符轉換成一個UCS-2字符。
若是轉換成功返回1,若是UTF-8字符是一個unrecognized字符,則返回0,且存一個blackbox(U+22e0)到ucs2_code_ptr中。
typedef unsigned short UINT16;
typedef unsigned char UINT8;
typedef unsigned char BOOL;
#define TRURE (BOOL)(1)
#define FALSE (BOOL)(0)
BOOL UTF8toUCS2Code(const UINT8* utf8_code, UINT16* ucs2_code){
UINT16 temp1, temp2;
BOOL is_unrecognized = FALSE ;
UINT16 * in = utf8_code;
if(!utf8_code || !ucs2_code){
return is_unrecognized;
}
if(0x00 == (*in & 0x80)){
/* 1 byte UTF-8 Charater.*/
*ucs2_code= (UINT16)*in;
is_unrecognized = TRUE;
}
else if(0xc0 == (*in & 0xe0) &&
0x80 == (*(in + 1) & 0xc0)
){
/* 2 bytes UTF-8 Charater.*/
temp1 = (UINT16)(*in & 0x1f);
temp1 <<= 6;
temp1 |= (UINT16)(*(in + 1) & 0x3f);
*ucs2_code = temp1;
is_unrecognized = TRUE;
}
else if( 0xe0 == (*in & 0xf0) &&
0x80 == (*(in +1) & 0xc0) &&
0x80 == (*(in + 2) & 0xc0)
){
/* 3bytes UTF-8 Charater.*/
temp1 = (UINT16)(*in &0x0f);
temp1 <<= 12;
temp2 = (UINT16)(*(in+1) & 0x3F);
temp2 <<= 6;
temp1 = temp1 | temp2 | (UINT16)(*(in+2) & 0x3F);
*ucs2_code = temp1;
is_unrecognized = TRUE;
}
else{
/* unrecognize byte. */
*ucs2_code = 0x22e0;
is_unrecognized = FALSE;
}
return is_unrecognized;
}
2,把一個UCS-2字符轉換成UTF-8字符。函數返回轉換成UTF-8的長度(字節1 -- 3),若是目標指針爲空,返回0。
UINT8 UCS2toUTF8Code(UINT16 ucs2_code, UINT8* utf8_code){
int length = 0;
UINT8* out = utf8_code;
if(!utf8_code){
return length;
}
if(0x0080 > ucs2_code){
/* 1 byte UTF-8 Character.*/
*out = (UINT8)ucs2_code;
length++;
}
else if(0x0800 > ucs2_code){
/*2 bytes UTF-8 Character.*/
*out = ((UINT8)(ucs2_code >> 6)) | 0xc0;
*(out+1) = ((UINT8)(ucs2_code & 0x003F)) | 0x80;
length += 2;
}
else{
/* 3 bytes UTF-8 Character .*/
*out = ((UINT8)(ucs2_code >> 12)) | 0xE0;
*(out+1) = ((UINT8)((ucs2_code & 0x0FC0)>> 6)) | 0x80;
*(out+2) = ((UINT8)(ucs2_code & 0x003F)) | 0x80;
length += 3;
}
return length;
}
字符串間的轉換也是同樣的。
[概述]
計算機中的一切都是以數字來表示的,字符一樣如此。字符編碼就是將字符集編碼成爲數字序列,以便能讓計算機識別。各個地區和國家使用的語言有別,將本地 使用的語言符號進行編碼就獲得本地編碼字符集。例如西歐國家使用的本地編碼是ISO8859-1,中國大陸和新加坡等地區使用本地編碼是GB2312或 GBK,中國港臺地區使用的本地編碼是BIG5,韓國和日本的本地編碼分別是euc-kr和Shift_JIS。電腦的操做系統支持各類本地編碼字符集, 操做系統默認的本地編碼和你所安裝的操做系統語言版本是一致的。本地集只對本地使用的文字符號進行了編碼,並不包括其餘地區使用的文字,即便兩個本地集中 包含了相同的字符,這個字符的編碼值也是不一樣的。例如「中」的GB2312或GBK編碼值爲「0xD6D0」,而BIG5編碼值爲「0xA4A4」。
全球信息交流與融合的趨勢要求實現對本地字符集的統一,1984年4月ISO成立了工做組,針對各國文字、符號進行統一編碼,這種編碼成爲 Unicode。Unicode於1992年6月經過DIS(DrafInternationalStandard),V2.0版本於1996年發佈。 Unicode編碼包括了符號6811個、漢字20902個、韓文11172個、等等。Unicode雖然實現了全球統一編碼,可是在字符集數量和編碼效 率方面顯然存在着不足,而UTF-八、UTF-16就是針對Unicode編碼進行轉換或擴充造成的編碼,UTF是Unicode Translation Format的縮寫。
[細節]
關於ASCII編碼
ASCII編碼是美國標準信息交換碼,這種編碼方式針對的是英文字符。 ASCII編碼使用一個字節對字符進行編碼,並且字節的最高位都爲0,所以ASCII編碼的字符集大小是128個。因爲英文字母僅有26個,再加上其餘一 些經常使用符號,總大小也不會超過128個,所以ASCII編碼的空間是足夠的。例如,字符「a」被編碼爲0x61,字符「b」被編碼爲0x62等等。注意, 在有的時候ASCII泛指本地編碼,例如文本編輯器UltraEdit中有諸如「ASCII轉Unicode」的功能,這裏的ASCII就泛指本地編碼, 若是本地編碼是GBK,這個功能執行的就是GBK編碼到Unicode編碼的轉換。
關於ISO8859-1編碼
ISO8859-1是西歐語系國家通用的字符集編碼,ISO8859-1使用一個字節對字符進行編碼,編碼值範圍是0x00-0xFF。其 中,0x00-0x1F用做控制字,0x20-0x7F表示字母、數字和符號這些圖形字符,0xA0-0xFF做爲附加部分使用。因爲ASCII編碼只使 用了一個字節中的低7位,編碼範圍僅爲0-127,雖然能夠容納英文字符和其餘的一些符號,可是卻不能包含除英文之外的其餘西歐語言的字母,所以 ASCII編碼在西歐國家並不通用。針對這個問題ISO在ASCII編碼的基礎上進行了擴充,制定了ISO8859-1編碼,ISO8859-1編碼使用 了一個字節的所有8位,編碼範圍是0-255,能包含西歐語系的全部字母和符號。
關於GB23十二、GBK和BIG5編碼
GB2312碼是中華人民共和國國家漢字信息交換使用碼,全稱《信息交換使用漢字編碼字符集-基本集》,由國家標準總局發佈,1981年5月1日實施,中國大陸和新加坡等地使用此編碼。GB2312收錄了簡化漢字、符號、字母、日文假名等共計7445個字符,其中漢字佔6763個。GB2312將代碼表分區94個區(0xA1-0xFE),對應第一個字節,每一個區94個位(0xA1-0xFE),對應了第二字節,兩個字節的值分別爲區號的值和位號的值加32(0x20),所以也被稱爲區位碼。GB2312的編碼範7圍是0x2121-0x777E,與ASCII有重疊,一般方法是將GB碼的兩個字節的最高位置1區別。
GBK是GB2312-80的擴展,向上兼容, 包含了20902個漢字,編碼範圍是0x8140-0xFEFE,剔除高位0x80的字位,其餘字符均可以一一映射到Unicode2.0。 GB18030-2000(GBK2K)在GBK的基礎上增長了藏、蒙等少數民族的字符,GBK2K從根本上解決了字位不夠、字形不足的問題。GBK2K 首先要求實現可以徹底映射到Unicode3.0標準的全部字形,如今尚未任何一個操做系統支持GBK2K。
BIG5碼被稱爲大五碼,是中國港臺地區使用的字符編碼方式。TW-BIG5碼將全部字分爲兩大羣,即經常使用字區和次經常使用字區,每一個字區分都採用筆畫排序,同筆畫的字依部首排序。TW-BIG5每一個字由兩個字節組成