Java字元丟失與中文編碼
來源:互聯網
上載者:User
編碼|中文 1. 引言
在用JAVA進行開發時,偶爾在IO操作中會產生字元丟失現象。如在用BEA的WORKSHOP開發CMP EJB過程中,總是編譯不通過,報錯:
cannot resolve symbol
symbol : class Excetion
location: class eaitest.vip.firmorder.FirmOrderBean_g8ghds__WebLogic_CMP_RDBMS
} catch (Excetion ex) {
可以看到明顯“Excetion”拼字錯誤。而這段代碼是WORKSHOP自動產生。但是,在某些機器上,同樣的工程檔案,編譯就能通過。聯絡BEA工程師,也不能解決此問題。
筆者查閱大量資料,很難找到相關問題的介紹。一次在偶爾查閱SUN的缺陷庫[i]時,發現是由於GB18030中文編碼問題所致。
2. 問題分析
國家標準GB18030-2000《資訊交換用漢字編碼字元集基本集的擴充》是我國繼GB2312-1980和GB13000-1993之後最重要的漢字編碼通訊協定,是我國電腦系統必須遵循的基礎性標準之一。國家質監總局規定GB 18030過渡期(即2001年8月31日)後正式發布或出廠的產品,必須符合GB-18030相關要求。
作業系統預設內部編碼一般並不是GB18030,目前已知在WINDOWS XP作業系統中,進行某些組件的升級後,會把作業系統的預設編碼由GB2312變更為GB18030。
但是即便在最新發行的JDK1.4.2_06版本中,對其支援仍存在一定問題。GB18030問題主要表現是,基於java的應用,涉及GB18030編碼與其它編碼方案轉換時,存在字元丟失現象。
問題的原因是java在處理由sun.nio.cs.ext.ExtendedCharsets提供的擴充字元集時,會進行字元緩衝。但是對於緩衝字元沒有採用新的sun.nio.cs.ext包處理,而是延用原有處理方式,這種方式在多線程操作下對GB18030編碼方案處理存在問題,這樣導致部分字元丟失。
此問題隻影響GB18030編碼方案,對GB2312等中文編碼方案並沒有影響。
當作業系統預設編碼方案為GB18030時,如果進行檔案寫操作,未指定編碼方案情況下,java採用作業系統預設編碼方案操作,這時最容易出現GB18030問題。
查看作業系統預設編碼,可以運行如下java程式:
public class EchoDefaultSystemEncoding{
public static void main(String[] args){
String encoding=System.getProperty(“file.encoding”);
System.out.println(“Default System Encoding: ” + encoding);
}
}
在用WORKSHOP開發CMP EJB出現問題的作業系統預設編碼即為GB18030。
由於遇到此問題的人比較少。而真正遇到時,很多人通過重新安裝作業系統可以解決問題,因而這方面的資料很難找到。
3. 解決辦法
最理想的解決辦法就是由SUN修正此BUG。此問題早在2003年11月即提出,但是直到目前(2004/12/30),問題狀態仍為“In process, bug”。
替代的解決方案主要思路是避開GB18030編碼,主要有兩種方法
改變作業系統預設編碼方案
對於unix/linux平台,修改作業系統編碼方案很簡單。如在solaris平台下,運行如下命令即可改變系統編碼:
LANG=zh.GBK;export LANG
對於windows平台,修改作業系統中文預設編碼比較複雜。嘗試把作業系統的“地區和語言選項”更改為其它地區,選用其它語言,都沒有效果。與微軟客戶服務聯絡,也不能提供相應解決方案。
運行java應用時指定預設編碼
在運行基於JAVA的應用時,加上參數:
java –Dfile.encoding=GB2312
把java應用的預設編碼方案與GB2312硬綁定,即在未指明編碼方案時,採用GB2312編碼。
如果針對每個應用,進行上述修改,工作量很大。有些應用裡面又隱式調用外部JAVA應用,更增加修正的難度。比較可行的辦法是對java的運行檔案進行修正,令其在運行時自動加上“-Dfile.encoding=GB2312”參數。
建議windows平台採用本方法進行修正。方案如下:
1、改名原java.exe,javaw.exe,如改為javabak.exe,javawbak.exe
2、重寫java.exe和javaw.exe,令其運行時調用javabak.exe,javawbak.exe,並在運行時加上“-Dfile.encoding”參數。
如下c代碼即可完成上述功能:
#include "string.h"
#include "stdlib.h"
int main(int argc, char* argv[])
{
char arg[100000] = "javabak.exe -Dfile.encoding=GB2312 ";
for(int i=1; i<argc; i++){
strcat(arg,argv[i]);
strcat(arg, " ");
}
system(arg);
return 0;
}
編譯後(注意修改arg值),產生的檔案命名為java.exe和javaw.exe,放置在<JAVA_HOME>/bin和<JAVA_HOME>/jre/bin目錄下,即可。
經實踐,此辦法可以解決GB18030問題,並且不會帶來其它隱患。唯一的缺點是在運行JAVA應用時,會有一個額外的DOS視窗開啟,此視窗可以關閉,不會對應用運行帶來影響。
4. 總結
在應用開發中,中文編碼一直是一個比較麻煩的問題。儘管目前GB18030是國家強制性標準,有著各種各樣的優點,但由於其推出時間尚短,在應用方面對其支援還不夠完善,還是應儘可能採用GB2312等相容性比較強的中文編碼方案。
本文給出的解決方案,不僅適用於解決JAVA平台對GB18030支援問題,而且,也為指定通用JAVA運行預設參數,提供了另一種思路。