對(duì)于Java中文問(wèn)題的幾條區(qū)分原則
發(fā)表時(shí)間:2024-05-20 來(lái)源:明輝站整理相關(guān)軟件相關(guān)文章人氣:
[摘要]盡管關(guān)于Java中文問(wèn)題的討論已經(jīng)相當(dāng)多了,但由于Java的相關(guān)技術(shù)標(biāo)準(zhǔn)繁多,面向Java的Web服務(wù)器、應(yīng)用服務(wù)器以及JDBC數(shù)據(jù)庫(kù)驅(qū)動(dòng)等都沒(méi)有官方的標(biāo)準(zhǔn),所以Java應(yīng)用在處理中文時(shí)所存在的問(wèn)題不僅沒(méi)有消失而且隨著所選用的服務(wù)器、驅(qū)動(dòng)程序以及運(yùn)行環(huán)境等因素的不同而變化。那么我們?nèi)绾螐谋姸喱F(xiàn)象中...
盡管關(guān)于Java中文問(wèn)題的討論已經(jīng)相當(dāng)多了,但由于Java的相關(guān)技術(shù)標(biāo)準(zhǔn)繁多,面向Java的Web服務(wù)器、應(yīng)用服務(wù)器以及JDBC數(shù)據(jù)庫(kù)驅(qū)動(dòng)等都沒(méi)有官方的標(biāo)準(zhǔn),所以Java應(yīng)用在處理中文時(shí)所存在的問(wèn)題不僅沒(méi)有消失而且隨著所選用的服務(wù)器、驅(qū)動(dòng)程序以及運(yùn)行環(huán)境等因素的不同而變化。那么我們?nèi)绾螐谋姸喱F(xiàn)象中找出問(wèn)題所在,并進(jìn)行分析和解決呢?與大部分的討論不同,本文將主要從如何預(yù)測(cè)、發(fā)現(xiàn)和檢查問(wèn)題的角度給出建議,幫助開(kāi)發(fā)人員找出可能引起問(wèn)題的各種源頭,從而更好地解決Java的中文問(wèn)題。
引言 盡管對(duì)于Java中文處理問(wèn)題的討論已不乏其數(shù),但由于Java技術(shù)涉及內(nèi)容廣(J2EE包含了十幾種相關(guān)技術(shù)),技術(shù)供應(yīng)商繁多,面向Java的Web服務(wù)器、應(yīng)用服務(wù)器以及JDBC數(shù)據(jù)庫(kù)驅(qū)動(dòng)等都沒(méi)有官方的標(biāo)準(zhǔn),所以Java應(yīng)用在處理中文過(guò)程中出了存在固有的問(wèn)題外也存在隨著選用的服務(wù)器,驅(qū)動(dòng)程序的不同而帶來(lái)的Java中文問(wèn)題的多變性,增加了問(wèn)題的復(fù)雜度。那么,我們?nèi)绾卧谶@么紛繁的現(xiàn)象中找到問(wèn)題的癥結(jié)呢?
Java中文問(wèn)題的一般解決辦法 事實(shí)上,Java的中文問(wèn)題都是由于Java應(yīng)用所采用的缺省編碼格式與目標(biāo)或者應(yīng)用所要讀入字符的編碼格式不同而造成的(具體參見(jiàn)文獻(xiàn)1)。對(duì)于如何解決Java的中文問(wèn)題,通常有四種方法:
1)選擇JDK的中文本地化版本。盡管Java2 JDK的中文本地化版本(http://java.sun.com/products/jdk/1.2/chinesejdk.html)并不是一個(gè)官方的版本,Sun公司也沒(méi)有承諾會(huì)對(duì)該本地化版本進(jìn)行升級(jí),但其仍不失為一個(gè)Java中文問(wèn)題的解決方案。
2)選擇合適的編譯參數(shù)。對(duì)于Java的國(guó)際版本來(lái)講,我們也可以在編譯Java應(yīng)用的時(shí)候通過(guò)指定確定的編碼機(jī)制來(lái)實(shí)現(xiàn)其編譯結(jié)果對(duì)中文的支持。例如,對(duì)于需要支持繁體中文和簡(jiǎn)體中文應(yīng)用可以通過(guò)javac -encoding big5 sourcefile.java 和javac -encoding gb2312 sourcefile.java來(lái)編譯源程序。
3)通過(guò)編程的方式實(shí)現(xiàn)字符編碼的轉(zhuǎn)換代碼。通過(guò)編程的方式來(lái)解決Java的中文問(wèn)題,已經(jīng)成為了一種較為普遍的做法。下面就是一種最常見(jiàn)的字符編碼轉(zhuǎn)換函數(shù),其將字符的編碼格式轉(zhuǎn)換為中文Windows系統(tǒng)的GBK編碼形式。
public static String toChinese(String strvalue)
{
try{
if(strvalue==null)
return null;
else
{
strvalue = new String(strvalue.getBytes("ISO8859_1"), "GBK");
return strvalue;
}
}catch(Exception e){
return null;
}
}
4)定義字符輸出集。對(duì)于JSP應(yīng)用,我們可以通過(guò)<%@ page contentType="text/html; charset=GBK" %>或<%@ page contentType="text/html; charset=GB2312" %>來(lái)定義JSP頁(yè)面的字符輸出集。當(dāng)然,我們也可以通過(guò)HTML的標(biāo)記來(lái)定義字符的輸出集。
存在的問(wèn)題
根據(jù)方法實(shí)現(xiàn)的方式,我們可以將以上四種方法分為兩類(lèi),一類(lèi)是通過(guò)利用某些標(biāo)準(zhǔn)或者規(guī)則來(lái)實(shí)現(xiàn)的方法,上面的1)、2)、4)都屬于此類(lèi);一類(lèi)是通過(guò)針對(duì)性的編程來(lái)實(shí)現(xiàn)的方法,上面所提的方法3)就屬于此類(lèi)。
由于方法1),2),4)是具有規(guī)范性的一類(lèi)方法,所以方法比較簡(jiǎn)單,解決方案也不具備較大的針對(duì)性,較為通用,例如我們可以采用方法2)的編譯方式通過(guò)編譯Java源文件來(lái)實(shí)現(xiàn)內(nèi)碼的預(yù)置,而無(wú)需考慮源碼到底有哪些部分出現(xiàn)了Java的中文處理問(wèn)題,諸如輸出亂碼等等。
但是,正由于這些方法不具備針對(duì)性,解決問(wèn)題的方法過(guò)于統(tǒng)一,所以在某些情況下,它們并不能徹底地解決Java的中文問(wèn)題。舉一個(gè)非常常見(jiàn)的例子。在通常情況下,用戶的Java應(yīng)用往往需要與其它Java應(yīng)用接口進(jìn)行交互,例如通過(guò)某種版本的JDBC訪問(wèn)數(shù)據(jù)庫(kù)。由于JDBC的驅(qū)動(dòng)所支持的編碼隨著提供商乃至版本的不同而不同,所以如果在數(shù)據(jù)庫(kù)的輸入輸出過(guò)程中出現(xiàn)中文不能正確處理問(wèn)題時(shí),我們需要在數(shù)據(jù)的輸入和輸出過(guò)程做兩次正好相反的編碼轉(zhuǎn)換,這對(duì)于方法1),2),4)來(lái)說(shuō),往往是無(wú)法解決的。當(dāng)然,對(duì)于方法2,我們也可以通過(guò)采用一些技巧使來(lái)滿足上面的情況,一個(gè)最有效的辦法就是盡量將Java應(yīng)用的各個(gè)部分組件化。例如我們可以通過(guò)將數(shù)據(jù)庫(kù)的讀入和輸出代碼分解在不同的源文件上來(lái)實(shí)現(xiàn)分別編譯,從而滿足不同的字符編碼要求。但是通常的程序設(shè)計(jì)都不太可能滿足這種要求,因?yàn)檫@種程序的劃分結(jié)果很可能是不合理的。例如,我們將數(shù)據(jù)庫(kù)的讀出和寫(xiě)入方法封裝到一個(gè)類(lèi)中是比較合適的一種設(shè)計(jì),但如果將該類(lèi)的這兩個(gè)方法分別實(shí)現(xiàn)在兩個(gè)文件里則變得非常不合理。因此對(duì)于1),2),4)方法來(lái)說(shuō),雖然實(shí)現(xiàn)比較簡(jiǎn)單,但卻具有一些無(wú)法克服的缺點(diǎn)。這也是那些實(shí)現(xiàn)起來(lái)相對(duì)復(fù)雜的編程方法得以流行的原因。
相對(duì)于方法1),2),4)來(lái)說(shuō),方法3)具有更好的針對(duì)性和靈活性。程序可以根據(jù)不同的情況做出靈活的處理,在任何需要的地方進(jìn)行字符的編碼轉(zhuǎn)換,但是該方法的特點(diǎn)也對(duì)軟件的開(kāi)發(fā)人員提出了更高要求--必須能夠準(zhǔn)確的捕捉到有可能發(fā)生中文處理問(wèn)題的地方,并做出正確的判斷和處理。