1. 程式人生 > >漢字編碼轉換原理及方法

漢字編碼轉換原理及方法

 

一、基本概念
· GB

全稱是GB2312-80《資訊交換用漢字編碼字符集 基本集》,1980年釋出,是中文資訊處理的國家標準,在大陸及海外使用簡體中文的地區(如新加坡等)是強制使用的唯一中文編碼。P-Windows3.2和蘋果OS就是以GB2312為基本漢字編碼, Windows 95/98則以GBK為基本漢字編碼、但相容支援GB2312GB碼共收錄6763個簡體漢字、682個符號,其中漢字部分:一級字3755,以拼音排序,二級字3008,以偏旁排序。該標準的制定和應用為規範、推動中文資訊化程序起了很大作用。1990年又制定了繁體字的編碼標準GB12345-90《資訊交換用漢字編碼字符集

第一輔助集》,目的在於規範必須使用繁體字的各種場合,以及古籍整理等。該標準共收錄6866個漢字(比GB2312103個字,其它廠商的字型檔大多不包括這些字),純繁體的字大概有2200餘個。(2312集與12345集不是相交的。一個是簡體,一個是繁體)
· BIG5

是目前臺灣、香港地區普遍使用的一種繁體漢字的編碼標準,包括440個符號,一級漢字5401個、二級漢字7652個,共計13060個漢字。Big-5 是一個雙位元組編碼方案,其第一位元組的值在 16 進位制的 A0FE 之間,第二位元組在 407E A1FE 之間。因此,其第一位元組的最高位是 1,第二位元組的最高位則可能是 1,也可能是 0

· GBK
編碼(Chinese Internal Code Specification)
GBK
編碼(俗稱大字符集)是中國大陸制訂的、等同於UCS的新的中文編碼擴充套件國家標準。GBK工作小組於199510月,同年12月完成GBK規範。該編碼標準相容GB2312,共收錄漢字21003個、符號883個,並提供1894個造字碼位,簡、繁體字融於一庫。Windows95/98簡體中文版的字型檔表層編碼就採用的是GBK,通過GBKUCS之間一一對應的碼錶與底層字型檔聯絡。其第一位元組的值在 16 進位制的 81FE 之間,第二位元組在 40FE,除去xx7F一線。
· Unicode
編碼(Universal Multiple Octet Coded Character Set)
國際標準組織於19844月成立ISO/IEC JTC1/SC2/WG2工作組,針對各國文字、符號進行統一性編碼。1991年美國跨國公司成立Unicode Consortium,並於199110月與WG2達成協議,採用同一編碼字集。目前Unicode是採用16位編碼體系,其字符集內容與ISO10646BMPBasic Multilingual Plane)相同。Unicode19926月通過DISDraf International Standard),目前版本V2.01996公佈,內容包含符號6811個,漢字20902個,韓文拼音11172個,造字區6400個,保留20249個,共計65534個。
二、一些註解
在此解釋一下我們常見的一些漢字內碼轉換工具:
1
最常見的是GB2Big5Big52GB轉換工具。這裡的GB指是GB2312集。
2
GBK簡體相容GB2312字符集及其編碼。不規範理解為GB就是GBK簡體。
3
繁體不等同於Big5,在GBK集中也有繁體,GB12345集也有繁體。但這三者的漢字編碼方式不同。Windows95/98/NT/2000(簡體中)中使用的都是GBK字符集;繁體版使用的是Big5字符集,在簡體版中無法正常顯示Big5字元,繁體版無法顯示GB字元。
4
IE中,進入Big5碼網站(如:臺灣網站),如果安裝有Big5字符集支援,IE會將Big5網頁轉換成GBK繁體顯示,沒有則是亂碼。IEGBK繁體顯示時,在網頁中輸入的漢字應當是GBK繁體,以Big5碼顯示時(亂碼),要輸入Big5碼字元(輸入亂碼? 先輸入GBK簡體----GB碼,再使用小工具將其轉換成Big5,拷貝,貼上即可)。
5
常見的小工具中,可將Big5轉換成GBK繁體的不多,可將GBK簡體繁體相互轉換的也不多。其原因是,他們是將GB2312字符集與Big5字符集建立了對應關係。

三、內碼轉換原理及方法
內碼轉換:就是在不同字符集之間建立一種對應關係。
GBK2Big5(簡繁體都可)
如:讓字,在GBK中編碼是C8C3。如果我們將GBK碼錶中的字元變成Big5碼格式,則C8C3位上的應該是字的Big5碼字元(琵字不是GBK中的琵,而是字的Big5碼漢字在GBK環境中顯示結果)。這樣我們讀出要轉換的文字,在GBK(已經轉換成Big5格式)碼錶中找到它的位置,取出該位置上的字元,將原字元替換即可。

讀寫字元不是問題。關鍵是如何在碼錶檔案中對該漢字進行定位和如何將純GBK碼錶轉換成Big5格式表示的GBK碼錶。
問題一、對漢字進行定位。
GBK
程式碼表(按程式碼順序排列)
81-87 88-8F 90-97 98-9F A0-A7 A8-AF B0-B7 B8-BF
C0-C7 C8-CF D0-D7 D8-DF E0-E7 E8-EF F0-F7 F8-FE

81 0 1 2 3 4 5 6 7 8 9 A B C D E F
4

5

6

7
乿  
8

9

A

B

C
伿
D

E

F
 


以上是按程式碼順序排列GBK碼錶,共126個區,每區190個漢字。漢字位置的計算如下:
posit = (ch1 - 129) * 190 + (ch2 - 64) - (ch2/128);
(第n 個漢字)
posit = posit * 2;
(第n個位元組)
第一個問題就算搞定。

問題二、將GBK碼錶用Big5來表示。
我們可以利用現有的工具,如東方快車3000,將GBK碼錶轉換成Big5的格式。但實際中有問題,因為GBKBig5的漢字要多,那麼在GBK中有的字元,而Big5中沒有的字元在轉換中可能被刪除,那上面後碼錶定位就不能用了。而且實際上幾乎無法定位。不過我在網上找到了一個以Big5表示的GBK碼錶的文字(可能是官方的),字元一個不缺。
這個問題也搞定了。


同樣我們可以進行
Big52GBKT
(繁體),Big52GBKS(簡體),GBKS2GBKTGBKT2GBKSGBK2BIG5的轉化。這裡給出Big5碼錶格式,和定位演算法:
BIG-5
程式碼表
A0-A7 A8-AF B0-B7 B8-BF C0-C7 C8-CF
D0-D7 D8-DF E0-E7 E8-EF F0-F7 F8-FE
(已被轉化成GBK
B0



退
 
 




 



定位方法:
if ((ch2 >= 64)&&(ch2 <= 126))
{
posit = (ch1 - 160) * 157 + (ch2 - 64);
posit = posit * 2 - 1;
}
else if ((ch2 >= 161)&&(ch2 <= 254))
{
posit = (ch1 - 160) * 157 + 62 + (ch2 - 160);
posit = posit * 2 - 1;
}

在這裡給出GBK2Big5C++Builder的程式:

fGBK2Big5 = fopen("pureGBK2Big5byOrder.txt", "rb");

unsigned long i,posit;//
gb碼轉換為gbkT
unsigned char ch1,ch2;
String sContext;
char chr;

sContext = Memo1->Lines->Text;
i=1;
while(i < sContext.Length())
{
ch1 = sContext[i];
ch2 = sContext[i+1];

if ((ch1 >= 129)&&(ch1 <= 254))
{
if (((ch2 >= 64)&&(ch2 < 127)) ||((ch2 > 127)&&(ch2 <= 254)))
{
posit = (ch1 - 129) * 190 + (ch2 - 64) - (ch2/128);
posit = posit * 2;
if ((posit > 23940*2) || (posit < 0))
{
i++;
continue;
}
fseek(fGBK2Big5, posit - ftell(fGBK2Big5), 1);
fread((void *)(&chr), sizeof(char), 1, fGBK2Big5);
sContext[i] = chr;
fread((void *)(&chr), sizeof(char), 1, fGBK2Big5);
sContext[i+1] = chr;
i +=2;
}
else
{
i++;
}
}
else
{
i++;
}
}

Memo1->Lines->Text=sContext;
以上很多資料來源於網路燈塔的參考資料(http://www.haiyan.com/steelk/navigator/ref/gbindex1.htm)。