java字符丟失與中文編碼
java字符丟失與中文編碼 警告:編碼 utf8 的不可映射字符 獲得ConnectionManager,設(shè)置相關(guān)參數(shù) 警告:編碼 utf8 的不可映射字符 標(biāo)志初始化是否完成的flag關(guān)鍵字: java字符丟失與中文編碼 1. 引言
在用JAVA進(jìn)行開(kāi)發(fā)時(shí),偶爾在IO操作中會(huì)產(chǎn)生字符丟失現(xiàn)象。如在用BEA的WORKSHOP開(kāi)發(fā)CMP EJB過(guò)程中,總是編譯不通過(guò),報(bào)錯(cuò):
cannot resolve symbol
symbol : class Excetion
location: class eaitest.vip.firmorder.FirmOrderBean_g8ghds__WebLogic_CMP_RDBMS
} catch (Excetion ex) {
可以看到明顯“Excetion”拼寫(xiě)錯(cuò)誤。而這段代碼是WORKSHOP自動(dòng)生成。但是,在某些機(jī)器上,同樣的工程文件,編譯就能通過(guò)。聯(lián)系BEA工程師,也不能解決此問(wèn)題。
筆者查閱大量資料,很難找到相關(guān)問(wèn)題的介紹。一次在偶爾查閱SUN的缺陷庫(kù)[i]時(shí),發(fā)現(xiàn)是由于GB18030中文編碼問(wèn)題所致。
2. 問(wèn)題分析
國(guó)家標(biāo)準(zhǔn)GB18030-2000《信息交換用漢字編碼字符集基本集的擴(kuò)充》是我國(guó)繼GB2312-1980和GB13000-1993之后最重 要的漢字編碼標(biāo)準(zhǔn),是我國(guó)計(jì)算機(jī)系統(tǒng)必須遵循的基礎(chǔ)性標(biāo)準(zhǔn)之一。國(guó)家質(zhì)監(jiān)總局規(guī)定GB 18030過(guò)渡期(即2001年8月31日)后正式發(fā)布或出廠的產(chǎn)品,必須符合GB-18030相關(guān)要求。
操作系統(tǒng)默認(rèn)內(nèi)部編碼一般并不是GB18030,目前已知在WINDOWS XP操作系統(tǒng)中,進(jìn)行某些組件的升級(jí)后,會(huì)把操作系統(tǒng)的默認(rèn)編碼由GB2312變更為GB18030。
但是即便在最新發(fā)布的JDK1.4.2_06版本中,對(duì)其支持仍存在一定問(wèn)題。GB18030問(wèn)題主要表現(xiàn)是,基于java的應(yīng)用,涉及GB18030編碼與其它編碼方案轉(zhuǎn)換時(shí),存在字符丟失現(xiàn)象。
問(wèn)題的原因是java在處理由sun.nio.cs.ext.ExtendedCharsets提供的擴(kuò)展字符集時(shí),會(huì)進(jìn)行字符緩沖。但是對(duì)于緩 沖字符沒(méi)有采用新的sun.nio.cs.ext包處理,而是延用原有處理方式,這種方式在多線程操作下對(duì)GB18030編碼方案處理存在問(wèn)題,這樣導(dǎo)致 部分字符丟失。
此問(wèn)題只影響GB18030編碼方案,對(duì)GB2312等中文編碼方案并沒(méi)有影響。
當(dāng)操作系統(tǒng)默認(rèn)編碼方案為GB18030時(shí),如果進(jìn)行文件寫(xiě)操作,未指定編碼方案情況下,java采用操作系統(tǒng)默認(rèn)編碼方案操作,這時(shí)最容易出現(xiàn)GB18030問(wèn)題。
查看操作系統(tǒng)默認(rèn)編碼,可以運(yùn)行如下java程序:
public class EchoDefaultSystemEncoding{
public static void main(String[] args){
String encoding=System.getProperty(“file.encoding”);
System.out.println(“Default System Encoding: ” + encoding);
}
}
在用WORKSHOP開(kāi)發(fā)CMP EJB出現(xiàn)問(wèn)題的操作系統(tǒng)默認(rèn)編碼即為GB18030。
由于遇到此問(wèn)題的人比較少。而真正遇到時(shí),很多人通過(guò)重新安裝操作系統(tǒng)可以解決問(wèn)題,因而這方面的資料很難找到。
3. 解決辦法
最理想的解決辦法就是由SUN修正此BUG。此問(wèn)題早在2003年11月即提出,但是直到目前(2004/12/30),問(wèn)題狀態(tài)仍為“In process, bug”。
替代的解決方案主要思路是避開(kāi)GB18030編碼,主要有兩種方法
改變操作系統(tǒng)默認(rèn)編碼方案
對(duì)于unix/linux平臺(tái),修改操作系統(tǒng)編碼方案很簡(jiǎn)單。如在solaris平臺(tái)下,運(yùn)行如下命令即可改變系統(tǒng)編碼:
LANG=zh.GBK;export LANG
對(duì)于windows平臺(tái),修改操作系統(tǒng)中文默認(rèn)編碼比較復(fù)雜。嘗試把操作系統(tǒng)的“區(qū)域和語(yǔ)言選項(xiàng)”更改為其它地區(qū),選用其它語(yǔ)言,都沒(méi)有效果。與微軟客戶服務(wù)聯(lián)系,也不能提供相應(yīng)解決方案。
運(yùn)行java應(yīng)用時(shí)指定默認(rèn)編碼
在運(yùn)行基于JAVA的應(yīng)用時(shí),加上參數(shù):
java –Dfile.encoding=GB2312
把java應(yīng)用的默認(rèn)編碼方案與GB2312硬綁定,即在未指明編碼方案時(shí),采用GB2312編碼。
如果針對(duì)每個(gè)應(yīng)用,進(jìn)行上述修改,工作量很大。有些應(yīng)用里面又隱式調(diào)用外部JAVA應(yīng)用,更增加修正的難度。比較可行的辦法是對(duì)java的運(yùn)行文件進(jìn)行修正,令其在運(yùn)行時(shí)自動(dòng)加上“-Dfile.encoding=GB2312”參數(shù)。
建議windows平臺(tái)采用本方法進(jìn)行修正。方案如下:
1、改名原java.exe,javaw.exe,如改為javabak.exe,javawbak.exe
2、重寫(xiě)java.exe和javaw.exe,令其運(yùn)行時(shí)調(diào)用javabak.exe,javawbak.exe,并在運(yùn)行時(shí)加上“-Dfile.encoding”參數(shù)。
如下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目錄下,即可。
經(jīng)實(shí)踐,此辦法可以解決GB18030問(wèn)題,并且不會(huì)帶來(lái)其它隱患。唯一的缺點(diǎn)是在運(yùn)行JAVA應(yīng)用時(shí),會(huì)有一個(gè)額外的DOS窗口打開(kāi),此窗口可以關(guān)閉,不會(huì)對(duì)應(yīng)用運(yùn)行帶來(lái)影響。
4. 總結(jié)
在應(yīng)用開(kāi)發(fā)中,中文編碼一直是一個(gè)比較麻煩的問(wèn)題。盡管目前GB18030是國(guó)家強(qiáng)制性標(biāo)準(zhǔn),有著各種各樣的優(yōu)點(diǎn),但由于其推出時(shí)間尚短,在應(yīng)用方面對(duì)其支持還不夠完善,還是應(yīng)盡可能采用GB2312等兼容性比較強(qiáng)的中文編碼方案。
本文給出的解決方案,不僅適用于解決JAVA平臺(tái)對(duì)GB18030支持問(wèn)題,而且,也為指定通用JAVA運(yùn)行默認(rèn)參數(shù),提供了另一種思路。
--------------------------------------------------------------------------------
參考文獻(xiàn)
[i] http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4954023
posted on 2009-05-20 12:54 找個(gè)美女做老婆 閱讀(262) 評(píng)論(0) 編輯 收藏