讓你的軟體支援正體中文

2021-08-22 01:23:59 字數 3814 閱讀 2882

讓你的軟體支援正體中文

中國台灣、香港的漢字用的是big5編碼,而大陸的漢字用的是gb編碼(gb2312也好,gbk也好),簡體中文軟體直接拿到正體中文環境下執行,問題就出來了。

怎麼辦呢?

我們的軟體是一款用c#.net+asp.net開發的,所謂b/s型的軟體,客戶端只須用瀏覽器訪問我們的伺服器就行了。很自然的就想到,把**中的所有的簡體字都轉換成繁體字,問題不就解決了嗎?

說幹就幹。從網上找來了一款轉換工具將全部**檔案轉換了一遍。編譯後執行,發覺靜態的文字或提示資訊確實已經變成了繁體,但從資料庫中拿出來的還是簡體(亂碼),轉換後的各種配置檔案也讀取出錯(因為程式仍然按gb編碼的格式進行讀取)。還有乙個問題,就是源**只能轉換一次。因為第一次轉換後gb變成了big5,如果再轉,就是big5轉big5,結果變得不可辨認。由於原始檔非常多,修改維護起來非常麻煩。

看來這種方法不可行。

那麼能不能給我們的軟體加上自適應的功能,增加對正體中文的支援呢?

asp.net中,頁面page有個物件response,該物件將http 響應資料傳送到客戶端,而response有個獲取或設定包裝篩選器物件的屬性filter,用於在傳輸之前修改http 實體主體。當建立stream 物件並將response.filter 屬性設定為stream 物件時,所有由response.write 傳送的http 輸出將通過篩選器。只要我們過載stream類,在stream類的write()方法中將gb碼轉換成big5碼,然後將response.filter = 過載stream類,就可以達到在資訊輸出到客戶端前先轉換的效果。

//頁面裝載事件

private void page_load(object sender, system.eventargs e)

簡體轉為繁體類cg2bfilter

public

class cg2bfilter : stream

//簡體轉為繁體

private

void writegb2big(byte buffer, int offset, int count)

//936

是簡體中文**頁編號

encoding e = encoding.getencoding(936);

string str = e.getstring(buffer,offset,count);

//有些簡體字沒有對應的big5,所以需要先轉換成繁體的gb,再進行轉換for( int i=0;i

}//950

是big5碼**頁編號

e = encoding.getencoding(950);

_sink.write(e.getbytes(str),0,e.getbytecount(str));}……

}這樣寫,是建立在待轉換的流全部都是gb編碼的基礎上的,而大多數情況下也沒有什麼問題,不過,如果乙個頁面存在表單控制項且控制項內有漢字內容隨同輸出時,那麼該頁面在執行過程中有回傳等重新整理動作的話,就可能出現亂碼。究其原因,是因為在頁面第一次開啟時,控制項值由簡體轉成了繁體,回傳的時候,則傳回伺服器的這部分控制項值也為繁體。接著再輸出,問題就來了:控制項值為繁體,而頁面本身還是簡體,也就是說,輸出流中存在混合編碼,這樣還一刀切將它們認為全是gb編碼來加以轉換就不行了,要加以區別。

怎麼區別呢?big5與gb有什麼區別嗎?很遺憾,並沒有什麼明顯的區別,也就是說,給你乙個漢字編碼,很難判斷它究竟是gb還是big5。一般傾向於認為低位元組在0x40~0x7f範圍的就是big5碼,因為沒有簡體字的低位元組在這個範圍。不過要注意,gb編碼也有繁體字,並且這些繁體字的低位元組也有位於0x40~0x7f的。所以這招並非萬靈丹。

將數值從高位元組0x81~0xff,低位元組0x40~0xff這樣組合輸出到頁面,如下:

string str = "";

encoding gbe = encoding.getencoding(936);

byte buffer = ;

for( byte y = 0x81;y<0xff;y++ )

}response.write(str);

然後在瀏覽器裡分別用gb編碼和big5編碼觀察,你會發現,這兩種編碼中,都存在著有些位元組值並沒有相應的漢字,而是一些奇怪的符號、問號甚至是空白。於是可以這樣認為:如果乙個漢字的位元組值在某種編碼中找不到漢字,則說明它不屬於這種編碼。經過認真比較歸納,兩種編碼都劃定了一些範圍,然後可以逐個考察輸出流中的漢字,看它是否落在該範圍,以此判定它屬於何種編碼。

雖然劃定了一些範圍,但gb和big5重疊的區域實在太多,有許多字用兩種編碼去套,好象都可以,逐個字轉換,誤差很大。後來發現了乙個很重要的思想,就是:在混合漢字編碼的流中,不同的漢字編碼總是不相鄰的,它們中間有西文字元隔開(因為網頁中,控制項值都包含在許多html標記之間),也就是說,如果有乙個漢字確定是某種編碼,則可以推斷與它相鄰的所有漢字都屬於同一種編碼。事實證明,這種思想使得轉換的準確性得到大幅度的提高。

修正後的類cg2bfilter:

public

class cg2bfilter : stream

p++;

if( p >= limit )

if( buffer[p] >= 0x40 && buffer[p] <= 0x7e

|| buffer[p-1] >= 0xa1 && buffer[p-1] <= 0xa3 && buffer[p] >= 0x40 && buffer[p] <= 0xa0

|| buffer[p-1] >= 0xa4 && buffer[p-1] <= 0xa9

|| ( buffer[p-1] >= 0xaa && buffer[p-1] <= 0xaf || buffer[p-1] >= 0xf8 && buffer[p-1] <= 0xfd ) && buffer[p] >= 0xa1 && buffer[p] <= 0xfe )

if( buffer[p] >= 0x7f && buffer[p] <= 0xa0

|| buffer[p-1] >= 0x81 && buffer[p-1] <= 0xa0

|| buffer[p-1] == 0xc6 && buffer[p] >= 0x7f && buffer[p] <= 0x0fe

|| buffer[p-1] >= 0xc7 && buffer[p-1] <= 0xc8

|| buffer[p-1] == 0xf9 && buffer[p] >= 0xdc

|| buffer[p-1] >= 0xfa )

}else

else

ischinese = false;

maybebig = false;

notbig = false;

q = p;}}

p++;}//

將while語句最後一輪迴圈未處理的部分在這裡處理

if( ischinese )

else

}else

}//處理物件為gb

private

void writegb2big(byte buffer, int offset, int count)

//處理物件為big5

private

void writebig(byte buffer, int offset, int count)

//處理物件為ascii

private

void writeascii(byte buffer, int offset, int count)……}

應用修正過的類後,瀏覽器用big5編碼瀏覽執行我們的軟體,效果令人非常滿意,幾乎看不到什麼亂碼,已經達到了實用的效果。不過繁簡切換是乙個相當複雜的問題,並不是僅僅是簡單地將簡體字轉換成繁體字就行了,有時還涉及到語義的問題。比如,簡體中文中,不論「發展」的「發」還是「頭髮」的「發」都是同乙個字,而在繁體中,它們是不同的兩個字。這部分已經超出了筆者現有的水平,不在考慮之列了。

讓你的軟體支援正體中文

讓你的軟體支援正體中文選擇自 leftfist 的 blog 關鍵字讓你的軟體支援正體中文 出處讓你的軟體支援正體中文 中國台灣 香港的漢字用的是 big5 編碼,而大陸的漢字用的是 gb編碼 gb2312 也好,gbk 也好 簡體中文軟體直接拿到正體中文環境下執行,問題就出來了。怎麼辦呢?我們的軟...

亞馬遜Kindle現開始支援正體中文內容的供應

據外媒報道,日前,亞馬遜宣布在其kindle電子閱讀器上加入對正體中文書籍的支援。亞馬遜指出 kindle的用程式設計客棧戶可以享受一些專為正體中文水平閱讀體驗而設計的功能,包括定製字型和在kindle裝置上使用正體中文搜尋的功能。使用免費kindle應用的使用者還可以選擇用正體中文顯示的選單選項。...

簡體中文與正體中文的轉換函式

unit unit1 inte ce uses windows,messages,sysutils,variants,classes,graphics,controls,forms,dialogs,stdctrls type tform1 class tform button1 tbutton pr...