評論:GB18030 - 想說(shuō)愛(ài)你不容易

發(fā)布時(shí)間:2013-4-21 21:12    發(fā)布者:1770309616
關(guān)鍵詞: GB18030 , 編碼 , ANSI編碼 , Unicode編碼 , 代碼
之所以會(huì )有此感嘆,并非覺(jué)得GB18030的編碼框架有什么不妥,而是對該標準在實(shí)際應用中遇到的尷尬情形的一些個(gè)人看法。

疑惑一:GB18030到底是一種ANSI編碼還是Unicode編碼?
這本來(lái)是毫無(wú)疑問(wèn)的,作為對GB2312和GBK的擴展,GB18030勢必要向下兼容這兩個(gè)編碼標準,而GB2312和GBK都是不折不扣的ANSI編碼,那么建立在這兩個(gè)標準基礎之上的GB18020也理所當然的應該是一種多字節的ANSI編碼了。

既然是ANSI編碼,那么在實(shí)際的系統中,它就應該是作為一種本地化的編碼字符集出現的。比如在Windows里面,它就應該像GBK、Big5這些 ANSI編碼那樣,有自己的代碼頁(yè)和相應的代碼頁(yè)屬性(主要指引導字節和尾隨字節的取值范圍)。對于代碼頁(yè),微軟已經(jīng)給出了答案:Win2k以上的操作系統只要安裝了微軟的GB18030-2000擴展支持包,就可以支持GB18020-2000編碼標準的54936代碼頁(yè)了。我在安裝了18030支持包之后,根據微軟給出的測試建議,寫(xiě)了個(gè)調用API函數IsValidCodePage(54936)的小程序,測試結果是54936代碼頁(yè)可用(未安裝 18030支持包以前,測試54936代碼頁(yè)不可用)。

但僅僅是某個(gè)代碼頁(yè)可用并不表示文本處理程序就可以處理基于該代碼頁(yè)編碼的文本了,還必須把這個(gè)代碼頁(yè)設為系統的當前代碼頁(yè)才行?墒,18030擴展包不是自帶了一個(gè)GB18030?Unicode的文本編碼轉換程序的嘛,這個(gè)程序并不需要把系統的當前代碼頁(yè)設為54936就可以工作呀。其實(shí),關(guān)于這一點(diǎn)花點(diǎn)時(shí)間想一下也很簡(jiǎn)單:文本文件的內碼轉換其實(shí)根本不需要操作系統的支持,這種轉碼工作在計算機文本處理任務(wù)中來(lái)說(shuō)算是最簡(jiǎn)單的了――說(shuō)得極端一點(diǎn),只要有轉碼表,我們甚至可以寫(xiě)一個(gè)在DOS下運行的GB18030?Unicode 轉碼程序,如果省去中文界面的話(huà),這個(gè)程序連中文系統都不用加載。在現實(shí)應用中,文本處理工作遠不只轉碼這一項,就拿日常用得比較多的文本編輯來(lái)說(shuō)吧―― 假設有一款以ANSI方式來(lái)處理文本的字處理軟件,如果想要在這個(gè)軟件中正確顯示和編輯GB18030編碼的文本的話(huà),首先就應該把系統的當前代碼頁(yè)設為 54936才行。這是因為代表GBK的936代碼頁(yè)的屬性和代表GB18030的54936代碼頁(yè)的屬性有很大的不同,在936代碼頁(yè)下,ANSI程序是無(wú)法正確處理GB18030編碼的文本的。

那么把系統的當前代碼頁(yè)設為54936不就好了嗎?可是事情好像并沒(méi)有那么簡(jiǎn)單……在編程時(shí),通過(guò)調用API函數GetACP可以獲得系統當前的代碼頁(yè),可是Win32 API里面并沒(méi)有對應提供一個(gè)類(lèi)似"SetACP"這樣的設置當前代碼頁(yè)的函數。事實(shí)上即使是Windows自己,也沒(méi)有辦法直接改變系統當前的代碼頁(yè), 改變當前代碼頁(yè)的方法是在控制面板中設置區域和語(yǔ)言選項,然后重啟才能生效。Windows區域和語(yǔ)言選項里面的"非Unicode程序語(yǔ)言版本"設置對 于普通電腦用戶(hù)來(lái)說(shuō)就是為那些只能處理特定語(yǔ)言的程序(ANSI文本處理程序)指定一個(gè)正確的,默認可以處理的語(yǔ)言種類(lèi)(比如是中文、日文或韓文);而對 于開(kāi)發(fā)ANSI文本處理程序的程序員來(lái)說(shuō),其實(shí)就是設置系統當前的代碼頁(yè)。比如要設置950代碼頁(yè)的時(shí)候,選"中文(臺灣)",要設置936代碼頁(yè)的時(shí)候,就選"中文(中國)"?墒亲屓穗y以理解的是,在安裝了18030支持包以后,"代碼頁(yè)轉換表"里面已經(jīng)顯示"54936(GB18030 簡(jiǎn)體中文)"代碼頁(yè)是可用使用的了。但在"非Unicode程序語(yǔ)言版本"列表里面,卻沒(méi)有相應地提供一個(gè)類(lèi)似"中文(中國GB18030)"這樣的選項,也就是說(shuō):Windows根本就沒(méi)有提供給我們把代表GB18030編碼標準的54936代碼頁(yè)設為系統當前代碼頁(yè)的選擇。難道微軟并不認為 GB18030是一種ANSI編碼,不需要相應的代碼頁(yè)支持?可是這個(gè)結論顯然跟微軟提供了54936這個(gè)代碼頁(yè)是相矛盾的,因為代碼頁(yè)本身就是處理不同本地化語(yǔ)言的一種機制,生來(lái)就是為ANSI編碼而設的。而且18030支持包里面的ReadMe文檔也透露了它附帶的轉碼程序其實(shí)是調用了API函數 MultiByteToWideChar和WideCharToMultiByte來(lái)實(shí)現的(否則無(wú)法解釋這個(gè)程序怎么會(huì )只有區區25KB之。,這就是說(shuō)微軟確實(shí)是把GB18030當作一種多字節的ANSI編碼來(lái)看待的?墒乾F在這個(gè)編碼的代碼頁(yè)卻根本不能設置為系統的當前代碼頁(yè)!這恐怕在 Windows所支持的所有代碼頁(yè)里面,是唯一的一個(gè)吧。

疑惑二:54936代碼頁(yè)的真相?既然CP54936在所有的代碼頁(yè)中顯得如此之特殊,這不得不讓人產(chǎn)生了一窺其具體技術(shù)細節的欲望。我們知道:對于代碼頁(yè)機制來(lái)說(shuō),不同代碼頁(yè)間的主要區別在于各個(gè)位置上的字節取值范圍的不同。比如 CP936的引導字節范圍在0x81-0xFE之間,尾隨字節范圍在0x40-0x7E或0x80-0xFE之間;CP932的引導字節范圍在 0x81-0x9F或0xE0-0xFC之間,尾隨字節范圍在0x40-0xFC(0x7F除外)之間。顯然CP936和CP932有 很大的不同,這種不同成了系統在當前代碼頁(yè)下,區分哪些是有效編碼(字符)和無(wú)效編碼(字符)的依據。言歸正傳,雖然Windows需要重啟才能改變當前 代碼頁(yè),但要查看某個(gè)代碼頁(yè)的信息卻不用那么麻煩。在任意一個(gè)代碼頁(yè)下,隨時(shí)都可以用API函數GetCPInfo讀出包括當前代碼頁(yè)在內的所有系統支持 的代碼頁(yè)的屬性信息。我們先用最熟悉的CP936試看看,測試結果GetCPInfo返回的信息如下:MaxCharSize=2;LeadByte= {81,FE,00,00,00,00,00,00,00,00,00,00}。這個(gè)結果的意思是說(shuō):CP936的字符最大編碼長(cháng)度是兩個(gè)字節,它的引導字節有一個(gè)取值范圍:0x81-0xFE。顯然GetCPInfo(936)返回的信息跟我們所了解的GBK編碼標準的技術(shù)框架是符合的。接下來(lái)看看我們所關(guān)心的CP54936的情況,測試結果GetCPInfo返回的信息如下:MaxCharSize=4;LeadByte= {00,00,00,00,00,00,00,00,00,00,00,00}。按照Windows代碼頁(yè)機制的說(shuō)法,這個(gè)結果意味著(zhù)CP54936沒(méi)有引導字節取值范圍的定義,而這種情況通常只有單字節ANSI編碼才會(huì )出現。難怪Windows沒(méi)有提供把54936設為系統當前代碼頁(yè)的選項了,因為即使把CP54936設為當前代碼頁(yè),那些ANSI字處理程序(也就是非Unicode程序)也是無(wú)法顯示和編輯GB18030編碼的文本的。這一點(diǎn)可以很容易地從Windows的代碼頁(yè)技術(shù)原理上分析得到:CP54936沒(méi)有定義引導字節的取值范圍,但它本身又是一種ANSI編碼的代碼頁(yè),所以當系統運行在這個(gè)代碼頁(yè)下的時(shí)候,實(shí)際上等于是運行在單字節ANSI編碼的代碼頁(yè)下面。這樣一來(lái),當我們試圖在A(yíng)NSI程序里面顯示一個(gè)四字節編碼的GB18030字符的時(shí)候,系統會(huì )毫不客氣地把它識別為無(wú)效編碼(字符),實(shí)際顯示出來(lái)的就是一堆的問(wèn)號了。這是因為單字節ANSI編碼的每個(gè)字節取值都不會(huì )超過(guò)0x7F 的,而GB18030的四字節編碼的第一、三個(gè)字節的取值都在0x81以上,根據Windows代碼頁(yè)的技術(shù)規則,當然會(huì )被判定為無(wú)效編碼(字符)了。

注:Windows 的代碼頁(yè)技術(shù)原理并不難理解。系統里面對應不同的代碼頁(yè)存儲了不同的代碼頁(yè)屬性――包括這個(gè)代碼頁(yè)所代表的編碼標準的最大字符存儲長(cháng) 度(單位:字節);引導字節取值范圍;尾隨字節取值范圍(這個(gè)是隱藏的,用GetCPInfo函數是得不到它的,但它確實(shí)存在,看來(lái)微軟還是習慣性地留了 一手)。系統存儲這些代碼頁(yè)屬性最主要的目的就是用來(lái)判斷某個(gè)給定的字符串里面是否包含有不符合當前代碼頁(yè)編碼框架的字符(編碼),當然這種判定是對于那 些準備要送去給程序中需要顯示在用戶(hù)界面上的字符串(文本)而言的。對于發(fā)生在計算機內部(內存)里面的文本處理過(guò)程(比如文本文件的內碼轉換),是不需 要進(jìn)行這種判斷的。這也就是為什么說(shuō)文本文件的轉碼不需要特定系統的支持的原因。系統判斷有效編碼(字符)和無(wú)效編碼(字符)的過(guò)程是這樣的:順序讀取字 符串中每個(gè)字節值,如果出現一個(gè)取值不在當前代碼頁(yè)屬性許可的取值范圍(比如在單字節代碼頁(yè)中出現大于0x7F的字節)內的字節的話(huà),那么這個(gè)字節所屬的字符就是無(wú)效字符,在軟件界面上就會(huì )被顯示為問(wèn)號。對于雙字節編碼的代碼頁(yè)(Windows支持的代碼頁(yè)都是單字節或雙字節代碼頁(yè),只有CP54936是四字節這個(gè)例外),如果讀出的某個(gè)字節值小于等于0x7F,就說(shuō)明它是一個(gè)單字節字符;如果讀出的字節值大于0x7F, 就把它當成引導字節處理,看看這個(gè)字節值是否在當前代碼頁(yè)指定的引導字節取值范圍內,以及它的下一個(gè)字節值是否在當前代碼頁(yè)指定的尾隨字節取值范圍內。如 果這兩個(gè)條件都成立,說(shuō)明當前讀到的這個(gè)字節和它的下一個(gè)字節組成了一個(gè)有效的雙字節字符,否則當前字節值判為無(wú)效編碼,顯示為問(wèn)號。

上述這個(gè)判定過(guò)程是真實(shí)存在的,完整的編碼有效性判定工作需要引導字節取值范圍和尾隨字節取值范圍兩個(gè)基本信息的支持。只是不知道微軟出于什么原因,只 開(kāi)放了引導字節取值范圍,但從Windows在文本處理上的一些行為中,是可以發(fā)現尾隨字節取值范圍信息是肯定存在的。比如,在簡(jiǎn)體中文系統下(CP936)寫(xiě)一個(gè)ANSI的小程序:這個(gè)程序的界面包括一個(gè)Edit控件和一個(gè)Button控件(兩個(gè)控件的字體屬性已經(jīng)設置成了"宋體-18030"),編寫(xiě)Button控件的鼠標單擊過(guò)程實(shí)現把一個(gè)編碼字節值序列為<82 34 84 34>的ANSI字符串賦值給那個(gè)Edit控件讓它顯示"䢎"(0x82348434是CJK ExtA漢字"䢎"的GB18030編碼)這個(gè)字的功能。做這個(gè)實(shí)驗程序的目的是要測試在CP936代碼頁(yè)下,ANSI程序是否能支持GB18030編碼字符的顯示和編輯。該程序的運行結果是,按下Button按鈕之后,Edit編輯框里面并沒(méi)有如希望的那樣顯示"䢎",而是??。顯然Windows認為在當前代碼頁(yè)(CP936)下面,0x82348434是兩個(gè)非法字符。因為這個(gè)編碼字節序列由四個(gè)字節組成,當系統讀出第一個(gè)字節0x82的時(shí)候,因為這個(gè)字節值大于0x7F,所以需要判斷它和下一個(gè)字節0x34能否組成一個(gè)雙字節字符,而由于0x34不在GBK尾隨字節取值范圍之內,所以第一和第二字節被判定為無(wú)效編碼;而第三字節的0x84和第四字節的0x34也是一樣的。所以這四個(gè)字節組成的編碼序列被判定為兩個(gè)無(wú)效字符,在軟件界面(Edit控件)上被顯示成了兩個(gè)問(wèn)號。系統的這一處理結果反映了尾隨字節取值范圍信息的真實(shí)存在,否則很難想象它怎么會(huì )把0x8234判斷為無(wú)效字符。因為根據雙字節ANSI編碼框架的一般規則:組成雙字節字符的前后兩個(gè)字節中,第一個(gè)字節必須大于0x7F以便文本處理程序把這個(gè)字節和單字節字符編碼區分開(kāi)來(lái)。而對第二個(gè)字節的取值范圍并不作特別的規定,可以是任意取值范圍(包括小于等于0x7F的ASCII編碼值范圍)。如果系統中沒(méi)有存儲GBK尾隨字節取值范圍定義的話(huà),由于第一個(gè)字節0x82已經(jīng)符合GBK引導字節取值范圍的要求了,第二個(gè)字節不管取什么值都應該判定這兩個(gè)字節組成的字符是有效的雙字節字符。而事實(shí)是Windows準確地判斷出了0x8234不符合GBK的雙字節編碼框架,這只能說(shuō)明它是清楚地知道GBK的尾隨字節取值范圍定義的。

實(shí)驗分析到這里,結論已經(jīng)很明顯了:在目前正式發(fā)行的Windows操作系統,包括微軟聲稱(chēng)能支持GB18030的Win2k、WinXP和Win2003 中,即使安裝了GB18030-2000擴展支持包,也不能真正使這些系統支持GB18030編 碼標準。因為道理再簡(jiǎn)單不過(guò)了,程序員根本就沒(méi)有辦法編寫(xiě)出能在這些系統下顯示和編輯GB18030-2000四字節編碼文本的ANSI文本處理程序。不 是很清楚這些系統是怎么通過(guò)GB18030-2000的標準符合性測試的。因為這些產(chǎn)品并不完全符合其中的"體系正確性:產(chǎn)品必須能夠正確識別和處理按照 國家標準GB 18030進(jìn)行編碼的文本文件。"這項要求。而微軟提供的GB18030支持包充其量只是提供了一個(gè)字體和幾個(gè)修改過(guò)的字符編碼轉換API函數,以及一個(gè)無(wú)法使用的CP54936,最后用一個(gè)其實(shí)跟系統支不支持GB18030標準并沒(méi)有關(guān)系的內碼轉換小程序就蒙混過(guò)關(guān)了。

為什么 GB18030制定出來(lái)已經(jīng)6年 了,卻一直沒(méi)有得到有效的應用?為什么我們大部分的應用程序還只能停留在處理GBK字符集的階段?為什么當我們很多公民在電腦中錄入自己包含生僻字的姓名 時(shí)仍然只能用×來(lái)代替?其實(shí)這并不怪GB18030-2000的編碼技術(shù)框架不好,而是相關(guān)部門(mén)在推廣應用該標準上虎頭蛇尾的態(tài)度造成的。單以編碼框架而 言,雖然一直被很多人視為Unicode/ISO10646的中國版(實(shí)際上也是)。但技術(shù)上還是有它自己獨到之處的,即使它的四字節編碼框架跟傳統的單 /雙字節ANSI編碼相比顯得不是那么的標準,但還不至于另類(lèi)到無(wú)法處理的地步。個(gè)人認為它的四字節編碼格式跟UTF-16編碼格式的代理對機制在處理思想上很有些相似之處,從應用層來(lái)說(shuō),單獨某款軟件要識別和處理這種單、雙、四字節混合編碼并不困難。但要把這些技術(shù)融入到整個(gè)操作系統之中,并不是簡(jiǎn)單地修改幾個(gè)API就能完成的,單是把Win32 API里面所有有關(guān)Ansi字符串處理的函數列出來(lái)就夠嚇人一跳的了。因為微軟不可能單為了一個(gè)GB18030放棄其他的ANSI編碼標準,加入對 GB18030的 支持必須是確保兼容原有的代碼頁(yè)機制的前提下才能實(shí)施的。而要保證這一點(diǎn),就必須對幾乎所有的字符串處理API進(jìn)行一定的修改?傊援斈甑那樾,微軟是 很難在短時(shí)間之內拿出完整的解決方案的。政府壓得急,微軟草草地拿出了個(gè)換湯不換藥的支持包應付了事,沒(méi)想到還真通過(guò)了。也不知道政府是不是真的不清楚這 個(gè)支持包的底細,反正自從這場(chǎng)"GB18030-2000標準之爭"以微軟推出擴展支持包這個(gè)皆大歡喜的體面方式收場(chǎng)之后,雙方好像就沒(méi)把推廣應用這回事 放心上了。幾年中就一直任由應用層面上這種不尷不尬的局面持續下來(lái),把一班滿(mǎn)心期待迎接GB18030時(shí)代卻又不明就里的中國應用開(kāi)發(fā)人員撩在了一邊。這些人在經(jīng)過(guò)了幾次徒勞的嘗試之后,終于還是放棄了支持GB18030標準的念頭,要么退回到GBK的小窩,要么踏上了Unicode未知的前程?傊诖蠹铱磥(lái)結論都是一樣的:對于Windows,GB18030是不可用的。

新版的GB18030-2005已經(jīng)出來(lái)了,雖然尚未有幸一睹標準原文真容,但希望它不會(huì )步GB18030-2000的后塵。落 個(gè)不尷不尬的局面吧,因然從長(cháng)遠來(lái)說(shuō)主流肯定是Unicode,但短期內仍然還是ANSI和Unicode并存的局面。像GB18030這種本地化版本的 Unicode還是需要的。希望它的應用價(jià)值不要被再度埋沒(méi)了。雖然這不是我這種小人物的努力就可以決定的。(cnBeta
本文地址:http://selenalain.com/thread-113926-1-1.html     【打印本頁(yè)】

本站部分文章為轉載或網(wǎng)友發(fā)布,目的在于傳遞和分享信息,并不代表本網(wǎng)贊同其觀(guān)點(diǎn)和對其真實(shí)性負責;文章版權歸原作者及原出處所有,如涉及作品內容、版權和其它問(wèn)題,我們將根據著(zhù)作權人的要求,第一時(shí)間更正或刪除。
您需要登錄后才可以發(fā)表評論 登錄 | 立即注冊

相關(guān)視頻

關(guān)于我們  -  服務(wù)條款  -  使用指南  -  站點(diǎn)地圖  -  友情鏈接  -  聯(lián)系我們
電子工程網(wǎng) © 版權所有   京ICP備16069177號 | 京公網(wǎng)安備11010502021702
快速回復 返回頂部 返回列表
午夜高清国产拍精品福利|亚洲色精品88色婷婷七月丁香|91久久精品无码一区|99久久国语露脸精品|动漫卡通亚洲综合专区48页