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-8

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”這三個字符用各種方式編碼後的結果如下:

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。 表示算法比較複雜,簡單說明如下:

  1. 從代碼點U中減去0x10000,得到U'。這樣U+10000~U+10FFFF就變成了 0x00000~0xFFFFF。
  2. 20位二進制數表示U'。 U'=yyyyyyyyyyxxxxxxxxxx
  3. 將前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 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-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、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字節模板了:1110xxxx 10xxxxxx10xxxxxx。將6C49寫成二進制是:0110 110001 001001, 用這個比特流依次代替模板中的x,得到:1110011010110001 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卻要用於實際的傳輸,所以就不得不考慮字節序的問題

 

談談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 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稱作“大尾”和“小尾”。

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字節模板了:1110xxxx 10xxxxxx10xxxxxx。將6C49寫成二進制是:0110 110001 001001, 用這個比特流依次代替模板中的x,得到:1110011010110001 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卻要用於實際的傳輸,所以就不得不考慮字節序的問題。

5、UTF的字節序和BOM

UTF-8以字節爲編碼單元,沒有字節序的問題UTF-16以兩個字節爲編碼單元,在解釋一個UTF-16文本前,首先要弄清楚每個編碼單元的字 節序。例如“奎”的Unicode編碼是594E,“乙”的Unicode編碼是4E59。如果我們收到UTF-16字節流“594E”,那麼這是“奎” 還是“乙”?

Unicode規範中推薦的標記字節順序的方法是BOM。BOM不是“Bill Of Material”的BOM表,而是Byte Order MarkBOM是一個有點小聰明的想法:

在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的編碼作爲一個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:  111111010xxxxxx 10xxxxxx 10xxxxxx10xxxxxx 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-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每個字由兩個字節組成


發佈了18 篇原創文章 · 獲贊 39 · 訪問量 30萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章