多種編碼的基本轉換(收集)

好久沒有來鋤草了,最近遇到編碼問題,記錄一下

 

主要包括區位碼,GB,GB2312,UNICODE,UTF-8,ISO8859-1。大部分爲轉載,如有錯誤,請高人指正。

 

GB2312和ISO8859-1無法直接轉換,這個問題頭疼,不過網上還是有解決方案的,如果是這個問題,大家就狗狗一下吧。

 

以下內容主要來自:http://www.mao2.com/papers/zhongwenbianma.html

http://hi.baidu.com/cuifenghui/blog/item/735b55da1804a1dfb7fd4817.html

 

1.區位碼: 

我國國家標準漢字信息交換用編碼,全稱《信息交換用漢字編碼字符集基本集》,標準號爲 GB 2312-80(GB 是“國標”二字的漢語拼音縮寫),由中華人民共和國國家標準總局發佈,1981年5月1日實施,新加坡等地也使用這一編碼。區位碼是一個四位的十進制數,它的前兩位叫做區碼,後兩位叫做位碼。區位碼的編碼範圍是:0101~9494。比如,按拼音排序後的第一個漢字是“啊”,它的區位碼爲1601(十六進制爲1001 H)。下圖是新華字典所顯示的漢字“啊”的信息。

 

2. 漢字國標碼(GB):

又稱交換碼,是一個碼集。將區位碼的十進制行列值轉換成16進制,再分別加上20H得到。舉例:將“萬”的區位碼轉換爲16進製表示:2D 52,分別加上20H得:4D 72,即爲國標碼。
由此,漢字第一個字節的最小值:10H + 20H =30H, 最大值:57H + 20H = 77H
第二個字節最小值: 01H + 20H = 21H, 最大值: 5EH + 20H = 7EH

 

3.GB2312 碼:

又稱爲國標碼,在區位碼的基礎上,分別將區號值和位號值各加 32(20H)而得到,於是它的編碼範圍是2121H~7E7EH,於是“啊”的GB2312 的編碼爲3021 H(即1001H+2020H)。但是,因爲GB2312 與ASCII有重疊,通行方法是將GB2312 碼兩個字節的最高位置1以示區別,編碼範圍變爲 0A1A1H~0FEFEH(實際只用到0xF7FEH)。這種在第八位置"1",提示計算機轉入雙字節的編碼方式也叫EUC(Extended UNIX Code)編碼,所以“啊”的GB2312 的最終編碼爲B0A1 H(即3021 H+8080H)。其實GB2312 和區位碼是一樣的,應該合在一起談。但事實上兩個的編碼又不一樣,我也不知爲什麼要弄得如此複雜。或許可以這樣理解:區位碼是一個編碼方案,而 GB2312 編碼則是這個方案在計算機裏的一個具體實現。GB2312 將收錄的漢字分成兩級:第一級是常用漢字計3755個,置於16-55區,按漢語拼音字母/筆形順序排列;第二級漢字是次常用漢字計3008個,置於 56-87區,按部首/筆畫順序排列。共計6763個漢字。

 

GB2312(1980年)一共收錄了7445個字符,包括6763個漢字和682個其它符號。漢字區的內碼範圍高字節從B0-F7,低字節從A1-FE,佔用的碼位是72*94=6768。其中有5個空位是D7FA-D7FE。GB2312-80中共收錄了7545個字符,用兩個字節編碼一個字符。每個字符最高位爲0。GB2312-80編碼簡稱國標碼。

  GB2312支持的漢字太少。1995年的漢字擴展規範GBK1.0收錄了21886個符號,它分爲漢字區和圖形符號區。漢字區包括21003個字符。

 

4. UNICODE

Unicode字符集(簡稱爲UCS),國際標準組織於1984年4月成立ISO/IECJTC1/SC2/WG2工作組,針對各國文字、符號進行統一性編碼。1991年美國跨國公司成立UnicodeConsortium,並於1991年10月與WG2達成協議,採用同一編碼字集。目前Unicode是採用16位編碼體系,其字符集內容與ISO10646的BMP(BasicMultilingual Plane)相同。Unicode於1992年6月通過DIS(DrafInternationalStandard),目前版本V2.0於1996公佈,內容包含符號6811個,漢字20902個,韓文拼音11172個,造字區6400個,保留20249個,共計65534個。Unicode編碼後的大小是一樣的.例如一個英文字母"a" 和 一個漢字"好",編碼後都是佔用的空間大小是一樣的,都是兩個字節!

Unicode可以用來表示所有語言的字符,而且是定長雙字節(也有四字節的)編碼,包括英文字母在內。所以可以說它是不兼容iso8859-1編碼的,也不兼容任何編碼。不過,相對於iso8859-1編碼來說,uniocode編碼只是在前面增加了一個0字節,比如字母'a'爲"0061"。
需要說明的是,定長編碼便於計算機處理(注意GB2312/GBK不是定長編碼),而unicode又可以用來表示所有字符,所以在很多軟件內部是使用unicode編碼來處理的,比如java。

 

隨着國際互聯網的迅速發展,要求進行數據交換的需求越來越大,不同的編碼體系越來越成爲信息交換的障礙,而且多種語言共存的文檔不斷增多,單靠代碼頁已很難解決這些問題,於是UNICODE應運而生。

UNICODE 通常用作涉及雙字節字符編碼方案的通用術語。UNICODE CCS 3.1(CCS:編碼字符集,coded character set) 的官方稱謂是 ISO10646-1 通用多八字節編碼字符集(Universal Multiple Octet Coded Character Set,UCS)。

UNICODE 編碼系統可分爲編碼方式和實現方式兩個層次。

目前用於實用的 UNICODE 版本的編碼方式使用16位的編碼空間,也就是每個字符佔用2個字節。這樣理論上一共最多可以表示 65536 個字符,基本滿足各種語言的使用。標準的UNICODE編碼方案使用32位的的編碼空間,目前編碼範圍是0到10FFFF H。例如“啊”的UNICODE編碼爲55 4A H。

UNICODE 的實現方式不同於編碼方式。一個字符的 UNICODE 編碼是確定的。但是在實際傳輸過程中,由於不同系統平臺對非ASCII碼的處理都不太一致,以及出於節省空間的目的,對 UNICODE 編碼的實現有着不同的方式。UNICODE 的實現方式稱爲UNICODE轉換格式(UNICODE Translation Format,簡稱爲 UTF)。常用的有:

1)UTF-8, 8bit編碼, ASCII不作變換, 其他字符做變長編碼, 每個字符1-6 byte。其與UNICODE編碼的關係如下:

U-00000000-U-0000007F: 0xxxxxxx
U-00000080-U-000007FF: 110xxxxx 10xxxxxx
U-00000800-U-0000FFFF: 1110xxxx 10xxxxxx 10xxxxxx
4-6位的UTF-8編碼對應着U-00010000-U-7FFFFFFF,比較少用到,就不列出了。
“啊”的UTF-8編碼是E5 95 8A,佔3字節。

2)UTF-16,16位編碼,基本上就是UNICODE編碼的實現。這裏只能說是“基本上”,因爲對於碼值在10000H到10FFFFH之間的 UNICODE碼,UTF-16是使用“代理對”(即兩個UNICODE碼)來實現編碼的。幸好,我們常用的字符,包括各國的文字、符號等,都可以使用單個UTF-16來編碼,不需要通過代理對實現。因此,UTF-16是UNICODE編碼實現的指定首選編碼方式。例如“啊”的UTF-16編碼是55 4A H,佔2字節,並且與實際“啊”的實用16位UNICODE編碼值是相等的。

3)UTF-32,32位編碼,顧名思義,與標準UNICODE編碼是一一對應的。例如“啊”的UTF-32編碼是00 00 55 4A,佔4字節。

上面羅列了一堆編碼,希望大家還沒有看暈過去。我們現在分析幾種JAVA中的亂碼問題。

首先,我們看看Window是如何處理文本文件的。Window2000內核是使用UNICODE編碼進行字符處理的。Window上的純文本編輯器(包括 JBuilder等JAVA開發工具的編輯器),在讀進一個純文本文件時,如果該文件本身沒有指定編碼格式,則編輯器會使用當前Window的代碼頁(中文Window下是CP936,即GBK)對文件內容字節流進行轉換,轉換成UNICODE編碼。在保存時,則將內存中的UNICODE編碼通過代碼頁轉換爲本地編碼,以字節流形式存入磁盤。

JAVA核心也使用UNICODE進行字符處理,與Window2000是一致的,因此,處理文件的過程也和上面是一樣的。因爲internet傳輸也是以字節流方式傳輸的,因此JAVA在處理網絡字節流時也按上述方式進行。在這種byte->char->byte類型的轉換中,如果中間出現編碼轉換錯誤,就會冒出中文亂碼問題了。

案例一:JAVA產生的文件(或控制檯輸出),在Window下正常,上傳到UNIX運行時亂碼。這是因爲兩臺機器的代碼頁不一致造成的。解決辦法:將UNIX上的語言區域設爲與Window的一致後,再運行JAVA程序。

案例二:文本文件使用Window文本編輯器可以正常打開,而JAVA應用程序讀入該文件時亂碼。原因是文本文件有多種的編碼方式包括ASCII,UTF- 8,UTF-16(而CPU有着字節順序的問題,故UTF-16又細分爲UTF-16LE小尾序、UTF-16BE大尾序兩種編碼)。文本文件在缺省下是根據當前系統的區域選定的編碼方式來保存的,Window下也就是代碼頁。解決辦法:檢查該文本文件的編碼方式,並在JAVA程序中按該編碼方式讀取數據。

 

5. UTF-8

在上面已經講述,其實是包含關係。

 

6. ISO8859-1:

屬於單字節編碼,最多能表示的字符範圍是0-255,應用於英文系列。比如,字母'a'的編碼爲0x61=97。

 

最常用的是ASCII編碼,編碼範圍是00 H-7F H。ISO8859編碼是對ASCII的擴展,擴展部分是80 H-FF H,用於定義其它非英文字母,如法語、德語等。其中ISO8859-1是最著名的一個,定義了西歐拉丁語符號。注意,ISO8859-1與GB18030 在編碼上也是重疊的。


很明顯,iso8859-1編碼表示的字符範圍很窄,無法表示中文字符。但是,由於是單字節編碼,和計算機最基礎的表示單位一致,所以很多時候,仍舊使用iso8859-1編碼來表示。而且在很多協議上,默認使用該編碼。比如,雖然"中文"兩個字不存在iso8859-1編碼,以gb2312編碼爲例,應該是"d6d0cec4"兩個字符,使用iso8859-1編碼的時候則將它拆開爲4個字節來表示:"d6d0 cec4"(事實上,在進行存儲的時候,也是以字節爲單位處理的)。而如果是UTF編碼,則是6個字節"e4b8 ad e6 96 87"。很明顯,這種表示方法還需要以另一種編碼爲基礎。

 

 

中文漢字編碼體系:

 

1.國家標準漢字代碼體系
   漢字字數繁多,屬性豐富,因而漢字代碼體系也較複雜,包括:
   (1)漢字機內碼。它們是漢字在計算機漢字系統內部的表示方法,是計算機漢字系統的基礎代碼。
   (2)漢字交換碼。它們是國標漢字(如機內碼)進行信息交換的代碼標準。
   (3)漢字輸入碼。它們是在計算機標準鍵盤上輸入漢字用到的各種代碼體系。
   (4)漢字點陣碼。它們是在計算機屏幕上顯示和在打印機上打印輸出漢字的代碼體系。
   (5)漢字字形控制碼。爲了打印各種風格的字體和字形所制定的代碼。
   這些代碼系統有的必須有統一的國家標準,有的則不要求統一。近年來我國已經制定系列漢字信息處理方面的國家標準,今後將繼續完善,並與國際上求得統一。

2. 國家標準漢字交換碼
   我國制定了“中華人民共和國國家標準信息交換漢字編碼”,標準代號爲GB2312—80,這種編碼又稱爲國標碼。在國標碼的字符集中共收錄了一級漢字3755個,二級漢字3008個,圖形符號682個,三項字符總計7445個。
   在國標GD2312—80中規定,所有的國標漢字及符號分配在一個94行、94列的方陣中,方陣的每一行稱爲一個“區”,編號爲01區到94區,每一列稱爲一個“位”,編號爲01位到94位,方陣中的每一個漢字和符號所在的區號和位號組合在一起形成的四個阿拉伯數字就是它們的“區位碼”。區位碼的前兩位是它的區號,後兩位是它的位號。用區位碼就可以唯一地確定一個漢字或符號,反過來說,任何一個漢字或符號也都對應着一個唯一的區位碼。漢字“母”字的區位碼是3624,表明它在方陣的36區24位,問號“?”的區位碼爲0331,則它在03區3l位。
   所有的漢字和符號所在的區分爲以下四個組:
(1)01區到15區。圖形符號區,其中01區到09區爲標準符號區,10區到15區爲自定義符號區。
   01區到09區的具體內容如下;
   1)01區。一般符號202個,如間隔符、標點、運算符、單位符號及製表符;
   2)02區。序號60個,如1.~20.、(1)~(20)、①~⑩及(一)~(十);
   3)03區。數字22個,如0—9及X一XII,英文字母52個,其中大寫A—Z、小寫a—z各26個;
   4)04區。日文平假名83個;
   5)05區。日文片假名86個;
   6)06區。希臘字母48個;
   7)07區。俄文字母66個;
   8)08區。漢語拼音符號a—z26個;
   9)09區。漢語拼音字母37個。
(2)16區到55區。一級常用漢字區,包括了3755個一統漢字。這40個區中的漢字是按漢語拼音排序的,同音字按筆劃順序排序。其中55區的90一94位未定義漢字。
(3)56區到87區。二級漢字區,包括了3008個二級漢字,按部首排序。
(4)88區到94區。自定義漢字區。
第10區到第15區的自定義符號區和第88區到第94區的自定義漢字區可由用戶自行定義國標碼中未定義的符號和漢字。

3. 國家標準漢字機內碼
漢字的機內碼是指在計算機中表示一個漢字的編碼。機內碼與區位碼稍有區別。如上所述,漢字區位碼的區碼和位碼的取值均在1~94之間,如直接用區位碼作爲機內碼,就會與基本ASCII碼混淆。爲了避免機內碼與基本ASCII碼的衝突,需要避開基本ASCII碼中的控制碼(00H~1FH),還需與基本ASCII碼中的字符相區別。爲了實現這兩點,可以先在區碼和位碼分別加上20H,在此基礎上再加80H(此處“H”表示前兩位數字爲十六進制數)。經過這些處理,用機內碼錶示一個漢字需要佔兩個字節,分別   稱爲高位字節和低位字節,這兩位字節的機內碼按如下規則表示:
高位字節=區碼+20H+80H(或區碼+A0H)
低位字節=位碼+20H+80H(或位碼+AOH)
由於漢字的區碼與位碼的取值範圍的十六進制數均爲01H~5EH(即十進制的01~94),   所以漢字的高位字節與低位字節的取值範圍則爲A1H~FEH(即十進制的161~254)。
例如,漢字“啊”的區位碼爲1601,區碼和位碼分別用十六進制表示即爲1001H,它的機內碼的高位字節爲B0H,低位字節爲A1H,機內碼就是B0A1H。  

4. 漢字的輸入碼
在計算機標準鍵盤上,漢字的輸入和西文的輸入有很大的不同。西文的輸入,擊一次鍵就直接輸入了相應的字符或代碼,“鍵入”和“輸入”是同一個含義。但是在計算機上進行漢字輸入時,“鍵入”是指擊鍵的動作即鍵盤操作的過程,而“輸入”則是把所需的漢字或字符送到指定的地方,是鍵盤操作的目的。目前已有多種漢字輸入方法,因此就有多種漢字輸入碼。漢字輸入碼是面向輸入者的,使用不同的輸入碼其操作過程不同,但是得到的結果是一樣的。不管採用何種輸入方法,所有輸入的漢字都以機內碼的形式存儲在介質中,而在進行漢字傳輸時,又都以交換碼的形式發送和接收。
國標GB2312—80規定的區位碼和沿用多年的電報碼都可以作爲輸入碼。這類漢字編碼和輸入碼是一一對應的,具有標準的性質,它們編碼用的字符是10個阿拉伯數字,每個漢字的碼長均爲等長的四個數碼。
其他編碼的種類很多,可從以下幾點加以討論:
(2)編碼類型。可分爲拼音碼、字形碼、音形結合碼等類型。
(2)編碼規則。不同的編碼方案有很大的不同,有的規則簡單,學習起來較容易記憶,‘有的規則複雜,較難記億。
(3)編碼字符集。有用字母鍵的,有用數字鍵的,有用字母鍵加數字鍵的,或者用了更多的鍵作編碼字符集的。
(4)編碼長度。它與編碼字符集的大小有關,字符集越大,編碼長度越短。採用26   個字母的編碼,其碼長一般爲四位。
(5)對應關係。除上面提到的區位碼和電報碼爲一一對應的無重碼編碼外,其他現有的編碼方案均有一定數量的重碼。所謂重碼即一碼對應多字。有許多編碼爲了增加輸入的靈活性,同一漢字用多個碼來對應,例如雙音編碼。
(6)單寧和詞彙的編碼。現有的編碼方案,爲了提高效率,除了單字外還規定了詞彙的編碼,甚至使用者可以自行增加詞彙庫中的詞彙,但在提高效率的同時也增加了記億和操作的複雜性。
(7)碼錶的類型和大小。從漢字輸入碼到機內碼的轉換一股需要在機內檢索碼錶。如果輸入碼和機內碼存在簡單的函數關係,有公式可以計算,如區位碼等編碼就不需要碼錶,其他沒有簡單函數關係的編碼就需要碼錶。碼錶大小與數據結構、單字數量、詞彙數量等因素有關。國標血2312—80規定的6763個一、二級漢字,備類編碼的碼錶從幾千字節到幾萬字節。隨着詞彙旦的增加,有的碼錶達到了若干兆字節。

5. 漢字的點陣碼
漢字的顯示和輸出,普遍採用點陣方法。由於漢字數量多且字形變化大,對不同字形漢字的輸出,就有不同的點陣字形。所謂漢字的點陣碼,就是漢字點陣字形的代碼。存儲在介質中的全部漢字的點陣碼又稱爲字庫。 .
   16x16點陣的漢字其點陣有16行,每一行上有16個點。如果每一個點用一個二進制位來表示,則每一行有16個二進制位,需用兩個字節來存放每一行上的16個點,並且規定其點陣中二進制位0爲白點,1爲黑點,這樣一個16X16點陣的漢字需要用2×t6即32個字節來存放。依次類推,24×24點陣和32×32點陣的漢字則依次要用72個字節和128個字節存放一個漢字,構成它在字庫中的字模信息。
要顯示或打印輸出一個漢字時,計算機漢字系統根據該漢字的機內碼找出其字模信息在字庫中的位置,再取出其字模信息作爲字形在屏幕上顯示或在打印機上打印輸出。

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