unicode和MBCS(多位元組字符集)的關係
轉載地址:http://my.oschina.net/alphajay/blog/5691
******************************************************************************************************************************************************
*****************************************************************************************************************************************************
談談Unicode編碼,簡要解釋UCS、UTF、BMP、BOM等名詞http://blog.csdn.net/smonster/archive/2008/10/31/3194587.aspx
unicode、ucs-2、ucs-4、utf-16、utf-32、utf-8http://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」這三個字元用各種方式編碼後的結果如下:
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 |
Windows平台下默認的Unicode編碼為Little Endian的UTF-16(即上述的 FF FE 41 00 42 00 43 00)。
UTF-16還能表示一部分的UCS-4代碼點——U+10000~U+10FFFF。 表示演算法比較複雜,簡單說明如下:
- 從代碼點U中減去0x10000,得到U"。這樣U+10000~U+10FFFF就變成了 0x00000~0xFFFFF。
- 用20位二進位數表示U"。 U"=yyyyyyyyyyxxxxxxxxxx
- 將前10位和後10位用W1和W2表示,W1=110110yyyyyyyyyy,W2=110111xxxxxxxxxx,則 W1 =D800~DBFF,W2 =DC00~DFFF。但是由於這種演算法的存在,造成UCS-2中的 U+D800~U+DFFF 變成了無定義的字元
UTF-32
UTF-32用四個位元組表示代碼點,這樣就可以完全表示UCS-4的所有代碼點,而無需像UTF-16那樣使用複雜的演算法。 與UTF-16類似,UTF-32也包括UTF-32、UTF-32BE、UTF-32LE三種編碼,UTF-32也同樣需要BOM字元。 僅用"ABC"舉例:
UTF-32BE | 00 00 00 4100 00 00 42 00 00 00 43 |
UTF-32LE | 41 00 00 0042 00 00 00 43 00 00 00 |
UTF-32(Big Endian) | 00 00 FE FF00 00 00 41 00 00 00 42 00 00 00 43 |
UTF-32(Little Endian) | FF FE 00 0041 00 00 00 42 00 00 00 43 00 00 00 |
UTF-32(不帶BOM) | 00 00 00 4100 00 00 42 00 00 00 43 |
UTF-8
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]。這樣只要看到第一個位元組的範圍就可以知道編碼的位元組數。 這樣也可以大大簡化演算法。
Unicode、UCS和UTF前面提到從ASCII、GB2312、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-8、UTF-7、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上一切規範的基礎。
2.1、內碼和code page
目前Windows的內核已經支持Unicode字符集,這樣在內核上可以支持全世界所有的語言文字。但是由於現有的大量程序和文檔都採用了某種特 定語言的編碼,例如GBK,Windows不可能不支持現有的編碼,而全部改用Unicode。
Windows使用代碼頁(code page)來適應各個國家和地區。code page可以被理解為前面提到的內碼。GBK對應的code page是CP936。
微軟也為GB18030定義了code page:CP54936。但是由於GB18030有一部分4位元組編碼,而Windows的代碼頁只支持單位元組和雙位元組編碼,所以這個code page是無法真正使用的。
3、UCS-2、UCS-4、BMPUCS有兩種格式: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之外。
4、UTF編碼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位元組模板了:1110xxxx10xxxxxx10xxxxxx。將6C49寫成二進位是:0110 110001 001001, 用這個比特流依次代替模板中的x,得到:111001101011000110001001,即 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卻要用於實際的傳輸,所以就不得不考慮位元組序的問題。
談談Unicode編碼,簡要解釋UCS、UTF、BMP、BOM等名詞這是一篇程序員寫給程序員的趣味讀物。所謂趣味是指可以比較輕鬆地了解一些原來不清楚的概念,增進知識,類似於打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)。但這些標記是基於什麼標準呢?
- 問題二:
- 最近在網上看到一個ConvertUTF.c,實現了UTF-32、UTF-16和UTF-8這三種編碼方式的相互轉換。對於 Unicode(UCS2)、GBK、UTF-8這些編碼方式,我原來就了解。但這個程序讓我有些糊塗,想不起來UTF-16和UCS2有什麼關係。
查了查相關資料,總算將這些問題弄清楚了,順帶也了解了一些Unicode的細節。寫成一篇文章,送給有過類似疑問的朋友。本文在寫作時盡量做到通 俗易懂,但要求讀者知道什麼是位元組,什麼是十六進位。
0、big endian和little endianbig endian和little endian是CPU處理多位元組數的不同方式。例如「漢」字的Unicode編碼是6C49。那麼寫到文件里時,究竟是將6C寫在前面,還是將49寫在前 面?如果將6C寫在前面,就是big endian。如果將49寫在前面,就是little endian。
「endian」這個詞出自《格列佛遊記》。小人國的內戰就源於吃雞蛋時是究竟從大頭(Big-Endian)敲開還是從小頭(Little- Endian)敲開,由此曾發生過六次叛亂,一個皇帝送了命,另一個丟了王位。
我們一般將endian翻譯成「位元組序」,將big endian和little endian稱作「大尾」和「小尾」。
1、字元編碼、內碼,順帶介紹漢字編碼字元必須編碼後才能被計算機處理。計算機使用的預設編碼方式就是計算機的內碼。早期的計算機使用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。按照程序員的稱呼,GB2312、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的位元組,就可以將下兩個位元組作為一個雙位元組編碼,而不用管低位元組的 高位是什麼。
2、Unicode、UCS和UTF
前面提到從ASCII、GB2312、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-8、UTF-7、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上一切規範的基礎。
2.1、內碼和code page
目前Windows的內核已經支持Unicode字符集,這樣在內核上可以支持全世界所有的語言文字。但是由於現有的大量程序和文檔都採用了某種特 定語言的編碼,例如GBK,Windows不可能不支持現有的編碼,而全部改用Unicode。
Windows使用代碼頁(code page)來適應各個國家和地區。code page可以被理解為前面提到的內碼。GBK對應的code page是CP936。
微軟也為GB18030定義了code page:CP54936。但是由於GB18030有一部分4位元組編碼,而Windows的代碼頁只支持單位元組和雙位元組編碼,所以這個code page是無法真正使用的。
3、UCS-2、UCS-4、BMP
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之外。
4、UTF編碼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位元組模板了:1110xxxx10xxxxxx10xxxxxx。將6C49寫成二進位是:0110 110001 001001, 用這個比特流依次代替模板中的x,得到:111001101011000110001001,即 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卻要用於實際的傳輸,所以就不得不考慮位元組序的問題。
5、UTF的位元組序和BOMUTF-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、D7、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的編碼作為一個LeadingByte,緊跟在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/encodingEF BB BF UTF-8FE FF UTF-16/UCS-2, little endianFF FE UTF-16/UCS-2, big endianFF 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 90EF 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 endianbig 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開頭 strcpyUnicode 操作函數以wcs開頭 wcscpyMBCS 操作函數以_mbs開頭 _mbscpyANSI/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 // !UNICODE7. 如何表示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 10xxxxxxU-00010000 - U-001FFFFF:11110xxx 10xxxxxx 10xxxxxx 10xxxxxxU-00200000 - U-03FFFFFF:111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxxU-04000000 - U-7FFFFFFF:1111110x10xxxxxx10xxxxxx10xxxxxx10xxxxxx10xxxxxx (很少用)在多位元組串中,第一個位元組的開頭『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-8、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,能包含西歐語系的所有字母和符號。關於GB2312、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每個字由兩個位元組組成 |
推薦閱讀:
※吃不吃早餐 和胖瘦關係不大
※六耳獼猴搶了唐僧的行李為何跑去花果山?只因他和孫悟空關係密切
※英語字母與音素的關係
※聲音合成秘密-濾波器與相位關係 - 縮混&錄音&拾音