久久国产成人av_抖音国产毛片_a片网站免费观看_A片无码播放手机在线观看,色五月在线观看,亚洲精品m在线观看,女人自慰的免费网址,悠悠在线观看精品视频,一级日本片免费的,亚洲精品久,国产精品成人久久久久久久

分享

編程技術中漢字問題的分析及解決

 duduwolf 2005-09-11
很難找到的一篇極棒的文章,,它從本質(zhì)上解決了java的漢字編碼問題............

在基于 Java 語言的編程中,,我們經(jīng)常碰到漢字的處理及顯示的問題,。一大堆看不懂的亂碼肯定不是我們愿意看到的顯示效果,怎樣才能夠讓那些漢字正確顯示呢,?Java 語言默認的編碼方式是UNICODE ,,而我們中國人通常使用的文件和數(shù)據(jù)庫都是基于 GB2312 或者 BIG5 等方式編碼的,怎樣才能夠恰當?shù)剡x擇漢字編碼方式并正確地處理漢字的編碼呢,?本文將從漢字編碼的常識入手,,結合 Java 編程實例,分析以上兩個問題并提出解決它們的方案,。

現(xiàn)在 Java 編程語言已經(jīng)廣泛應用于互聯(lián)網(wǎng)世界,,早在 Sun 公司開發(fā) Java 語言的時候,就已經(jīng)考慮到對非英文字符的支持了,。Sun 公司公布的 Java 運行環(huán)境(JRE)本身就分英文版和國際版,,但只有國際版才支持非英文字符。不過在 Java 編程語言的應用中,,對中文字符的支持并非如同 Java Soft 的標準規(guī)范中所宣稱的那樣完美,,因為中文字符集不只一個,而且不同的操作系統(tǒng)對中文字符的支持也不盡相同,所以會有許多和漢字編碼處理有關的問題在我們進行應用開發(fā)中困擾著我們,。有很多關于這些問題的解答,,但都比較瑣碎,并不能夠滿足大家迫切解決問題的愿望,,關于 Java 中文問題的系統(tǒng)研究并不多,,本文從漢字編碼常識出發(fā),分析 Java 中文問題,,希望對大家解決這個問題有所幫助,。

漢字編碼的常識

我們知道,英文字符一般是以一個字節(jié)來表示的,,最常用的編碼方法是 ASCII ,。但一個字節(jié)最多只能區(qū)分256個字符,而漢字成千上萬,,所以現(xiàn)在都以雙字節(jié)來表示漢字,,為了能夠與英文字符分開,每個字節(jié)的最高位一定為1,,這樣雙字節(jié)最多可以表示64K格字符,。我們經(jīng)常碰到的編碼方式有 GB2312、BIG5,、UNICODE 等,。關于具體編碼方式的詳細資料,有興趣的讀者可以查閱相關資料,。我膚淺談一下和我們關系密切的 GB2312 和 UNICODE,。GB2312 碼,中華人民共和國國家標準漢字信息交換用編碼,,是一個由中華人民共和國國家標準總局發(fā)布的關于簡化漢字的編碼,,通行于中國大陸地區(qū)及新加坡,簡稱標碼,。兩個字節(jié)中,,第一個字節(jié)(高字節(jié))的值為區(qū)號值加32(20H),第二個字節(jié)(低字節(jié))的值為位號值加32(20H),,用這兩個值來表示一個漢字的編碼,。UNICODE 碼是微軟提出的解決多國字符問題的多字節(jié)等長編碼,它對英文字符采取前面加"0"字節(jié)的策略實現(xiàn)等長兼容,。如 "A" 的 ASCII 碼為0x41,,UNICODE 就為0x00,0x41,。利用特殊的工具各種編碼之間可以互相轉(zhuǎn)換,。

Java 中文問題的初步認識

我們基于 Java 編程語言進行應用開發(fā)時,,不可避免地要處理中文。Java 編程語言默認的編碼方式是 UNICODE,,而我們通常使用的數(shù)據(jù)庫及文件都是基于 GB2312 編碼的,,我們經(jīng)常碰到這樣的情況:瀏覽基于 JSP 技術的網(wǎng)站看到的是亂碼,文件打開后看到的也是亂碼,,被 Java 修改過的數(shù)據(jù)庫的內(nèi)容在別的場合應用時無法繼續(xù)正確地提供信息,。

String sEnglish = "apple";

String sChinese = "蘋果";

String s = "蘋果 apple ";

sEnglish 的長度是5,sChinese的長度是4,,而 s 默認的長度是14,。對于 sEnglish來說, Java 中的各個類都支持得非常好,,肯定能夠正確顯示,。但對于 sChinese 和 s 來說,雖然 Java Soft 聲明 Java 的基本類已經(jīng)考慮到對多國字符的支持(默認 UNICODE 編碼),,但是如果操作系統(tǒng)的默認編碼不是 UNICODE ,,而是國標碼等。從 Java 源代碼到得到正確的結果,,要經(jīng)過 "Java 源代碼-> Java 字節(jié)碼-> ;虛擬機->操作系統(tǒng)->顯示設備"的過程,。在上述過程中的每一步驟,我們都必須正確地處理漢字的編碼,,才能夠使最終的顯示結果正確,。

" Java 源代碼-> Java 字節(jié)碼",標準的 Java 編譯器 javac 使用的字符集是系統(tǒng)默認的字符集,,比如在中文 Windows 操作系統(tǒng)上就是 GBK ,而在 Linux 操作系統(tǒng)上就是ISO-8859-1,,所以大家會發(fā)現(xiàn)在 Linux 操作系統(tǒng)上編譯的類中源文件中的中文字符都出了問題,解決的辦法就是在編譯的時候添加 encoding 參數(shù),,這樣才能夠與平臺無關,。用法是

javac -encoding GBK,。

" Java 字節(jié)碼->虛擬機->操作系統(tǒng)",, Java 運行環(huán)境 (JRE) 分英文版和國際版,但只有國際版才支持非英文字符,。 Java 開發(fā)工具包 (JDK) 肯定支持多國字符,,但并非所有的計算機用戶都安裝了 JDK 。很多操作系統(tǒng)及應用軟件為了能夠更好的支持 Java ,,都內(nèi)嵌了 JRE 的國際版本,,為自己支持多國字符提供了方便。

"操作系統(tǒng)->顯示設備",,對于漢字來說,,操作系統(tǒng)必須支持并能夠顯示它,。英文操作系統(tǒng)如果不搭配特殊的應用軟件的話,是肯定不能夠顯示中文的,。

還有一個問題,,就是在 Java 編程過程中,對中文字符進行正確的編碼轉(zhuǎn)換,。例如,,向網(wǎng)頁輸出中文字符串的時候,不論你是用out.println(string);還是用<%=string%>,,都必須作 UNICODE 到 GBK 的轉(zhuǎn)換,,或者手動,或者自動,。在 JSP 1.0中,,可以定義輸出字符集,從而實現(xiàn)內(nèi)碼的自動轉(zhuǎn)換,。用法是

<%@page contentType="text/html;charset=gb2312" %>

但是在一些 JSP 版本中并沒有提供對輸出字符集的支持,,(例如 JSP 0.92),這就需要手動編碼輸出了,,方法非常多,。最常用的方法是

String s1 = request.getParameter("keyword");

String s2 = new String(s1.getBytes("ISO-8859-1"),"GBK");

getBytes 方法用于將中文字符以"ISO-8859-1"編碼方式轉(zhuǎn)化成字節(jié)數(shù)組,而"GBK" 是目標編碼方式,。我們從以ISO-8859-1方式編碼的數(shù)據(jù)庫中讀出中文字符串 s1 ,,經(jīng)過上述轉(zhuǎn)換過程,在支持 GBK 字符集的操作系統(tǒng)和應用軟件中就能夠正確顯示中文字符串 s2 ,。

Java 中文問題的表層分析及處理

背景

開發(fā)環(huán)境

JDK1.15

Vcafe2.0

JPadPro

服務器端

NT IIS

Sybase System

Jconnect(JDBC)

客戶端

IE5.0

Pwin98

span >

.CLASS 文件存放在服務器端,,由客戶端的瀏覽器運行 APPLET , APPLET 只起調(diào)入FRAME 類等主程序的作用,。界面包括 Textfield ,,TextArea,List,,Choice 等,。

I.用 JDBC 執(zhí)行 SELECT 語句從服務器端讀取數(shù)據(jù)(中文)后,將數(shù)據(jù)用 APPEND 方法加到 TextArea(TA) ,,不能正確顯示,。但加到 List 中時,大部分漢字卻可正確顯示,。

將數(shù)據(jù)按"ISO-8859-1" 編碼方式轉(zhuǎn)化為字節(jié)數(shù)組,,再按系統(tǒng)缺省編碼方式 (Default Character Encoding) 轉(zhuǎn)化為 STRING ,即可在 TA 和 List 中正確顯示,。

程序段如下:

dbstr2 = results.getString(1);

//After reading the result from DB server,,converting it to string.

dbbyte1 = dbstr2.getBytes("iso-8859-1");

dbstr1 = new String(dbbyte1);

在轉(zhuǎn)換字符串時不采用系統(tǒng)默認編碼方式,,而直接采用" GBK" 或者 "GB2312" ,在 A 和 B 兩種情況下,從數(shù)據(jù)庫取數(shù)據(jù)都沒有問題,。

II.處理方式與"取中文"相逆,,先將 SQL 語句按系統(tǒng)缺省編碼方式轉(zhuǎn)化為字節(jié)數(shù)組,再按"ISO-8859-1"編碼方式轉(zhuǎn)化為 STRING ,,最后送去執(zhí)行,,則中文信息可正確寫入數(shù)據(jù)庫。

程序段如下:

sqlstmt = tf_input.getText();

//Before sending statement to DB server,,converting it to sql statement.

dbbyte1 = sqlstmt.getBytes();

sqlstmt = newString(dbbyte1,"iso-8859-1");

_stmt = _con.createStatement();

_stmt.executeUpdate(sqlstmt);

......

問題:如果客戶機上存在 CLASSPATH 指向 JDK 的 CLASSES.ZIP 時(稱為 A 情況),,上述程序代碼可正確執(zhí)行。但是如果客戶機只有瀏覽器,,而沒有 JDK 和 CLASSPATH 時(稱為 B 情況),,則漢字無法正確轉(zhuǎn)換。

我們的分析:

1.經(jīng)過測試,,在 A 情況下,,程序運行時系統(tǒng)的缺省編碼方式為 GBK 或者 GB2312 。在 B 情況下,,程序啟動時瀏覽器的 JAVA 控制臺中出現(xiàn)如下錯誤信息:

Can‘t find resource for sun.awt.windows.awtLocalization_zh_CN

然后系統(tǒng)的缺省編碼方式為"8859-1",。

2.如果在轉(zhuǎn)換字符串時不采用系統(tǒng)缺省編碼方式,而是直接采用 "GBK" 或"GB2312",,則在 A 情況下程序仍然可正常運行,,在 B 情況下,系統(tǒng)出現(xiàn)錯誤:

UnsupportedEncodingException,。

3.在客戶機上,,把 JDK 的 CLASSES.ZIP 解壓后,放在另一個目錄中,, CLASSPATH 只包含該目錄,。然后一邊逐步刪除該目錄中的 .CLASS 文件,另一邊運行測試程序,,最后發(fā)現(xiàn)在一千多個 CLASS 文件中,,只有一個是必不可少的,該文件是:

sun.io.CharToByteDoubleByte.class,。

將該文件拷到服務器端和其它的類放在一起,,并在程序的開頭 IMPORT 它,在 B 情況下程序仍然無法正常運行,。

4.在A 情況下,如果在 CLASSPTH 中去掉 sun.io.CharToByteDoubleByte.class ,,則程序運行時測得默認編碼方式為"8859-1",,否則為 "GBK" 或 "GB2312" ,。

如果 JDK 的版本為1.2以上的話,在 B 情況下遇到的問題得到了很好的解決,,測試的步驟同上,,有興趣的讀者可以嘗試一下。

Java 中文問題的根源分析及解決

在簡體中文 MS Windows 98 + JDK 1.3 下,,可以用 System.getProperties() 得到 Java 運行環(huán)境的一些基本屬性,,類 PoorChinese 可以幫助我們得到這些屬性。

類 PoorChinese 的源代碼:

public class PoorChinese {

}

執(zhí)行 java PoorChinese 后,,我們會得到:

系統(tǒng)變量 file.encoding 的值為 GBK ,,user.language 的值為 zh , user.region 的值為 CN ,,這些系統(tǒng)變量的值決定了系統(tǒng)默認的編碼方式是 GBK ,。

在上述系統(tǒng)中,下面的代碼將 GB2312 文件轉(zhuǎn)換成 Big5 文件,,它們能夠幫助我們理解 Java 中漢字編碼的轉(zhuǎn)化:

import java.io.*;

import java.util.*;

public class gb2big5 {

static int iCharNum=0;

public static void main(String[] args) {

System.out.println("Input GB2312 file, output Big5 file.");

if (args.length!=2) {

System.err.println("Usage: jview gb2big5 gbfile big5file");

System.exit(1);

String inputString = readInput(args[0]);

writeOutput(inputString,args[1]);

System.out.println("Number of Characters in file: "+iCharNum+".");

}

static void writeOutput(String str, String strOutFile) {

try {

FileOutputStream fos = new FileOutputStream(strOutFile);

Writer out = new OutputStreamWriter(fos, "Big5");

out.write(str);

out.close();

}

catch (IOException e) {

e.printStackTrace();

e.printStackTrace();

}

}

static String readInput(String strInFile) {

StringBuffer buffer = new StringBuffer();

try {

FileInputStream fis = new FileInputStream(strInFile);

InputStreamReader isr = new InputStreamReader(fis, "GB2312");

Reader in = new BufferedReader(isr);

int ch;

while ((ch = in.read()) > -1) {

iCharNum += 1;

buffer.append((char)ch);

}

in.close();

return buffer.toString();

}

catch (IOException e) {

e.printStackTrace();

return null;

}

}

}

編碼轉(zhuǎn)化的過程如下:

GB2312------------------>Unicode------------->Big5

執(zhí)行 java gb2big5 gb.txt big5.txt ,,如果 gb.txt 的內(nèi)容是"今天星期三",則得到的文件 big5.txt 中的字符能夠正確顯示,;而如果 gb.txt 的內(nèi)容是"情人節(jié)快樂",,則得到的文件 big5.txt 中對應于"節(jié)"和"樂"的字符都是符號"?"(0x3F),,可見 sun.io.ByteToCharGB2312 和 sun.io.CharToByteBig5 這兩個基本類并沒有編好,。

正如上例一樣, Java 的基本類也可能存在問題,。由于國際化的工作并不是在國內(nèi)完成的,,所以在這些基本類發(fā)布之前,沒有經(jīng)過嚴格的測試,,所以對中文字符的支持并不像 Java Soft 所聲稱的那樣完美,。前不久,我的一位技術上的朋友發(fā)信給我說,,他終于找到了 Java Servlet 中文問題的根源,。兩周以來,他一直為 Java Servlet 的中文問題所困擾,,因為每面對一個含有中文字符的字符串都必須進行強制轉(zhuǎn)換才能夠得到正確的結果(這好象是大家公認的唯一的解決辦法),。后來,他確實不想如此繼續(xù)安分下去了,,因為這樣的事情確實不應該是高級程序員所要做的工作,,他就找出 Servlet 解碼的源代碼進行分析,因為他懷疑問題就出在解碼這部分,。經(jīng)過四個小時的奮斗,,他終于找到了問題的根源所在,。原來他的懷疑是正確的, Servlet 的解碼部分完全沒有考慮雙字節(jié),,直接把 %XX 當作一個字符,。(原來 Java Soft 也會犯這幺低級的錯誤!)

如果你對這個問題有興趣或者遇到了同樣的煩惱的話,,你可以按照他的步驟Servlet.jar 進行修改

找到源代碼 HttpUtils 中的 static private String parseName ,,在返回前將 sb(StringBuffer) 復制成 byte bs[] ,然后 return new String(bs,"GB2312"),。作上述修改后就需要自己解碼了:

HashTable form=HttpUtils .parseQueryString(request.getQueryString())或者

form=HttpUtils.parsePostData(......)

千萬別忘了編譯后放到 Servlet.jar 里面,。

五、 關于 Java 中文問題的總結

Java 編程語言成長于網(wǎng)絡世界,,這就要求 Java 對多國字符有很好的支持,。 Java 編程語言適應了計算的網(wǎng)絡化的需求,為它能夠在網(wǎng)絡世界迅速成長奠定了堅實的基礎,。 Java 的締造者 (Java Soft) 已經(jīng)考慮到 Java 編程語言對多國字符的支持,,只是現(xiàn)在的解決方案有很多缺陷在里面,需要我們付諸一些補償性的措施,。而世界標準化組織也在努力把人類所有的文字統(tǒng)一在一種編碼之中,,其中一種方案是 ISO10646 ,它用四個字節(jié)來表示一個字符,。當然,,在這種方案未被采用之前,還是希望 Java Soft 能夠嚴格地測試它的產(chǎn)品,,為用戶帶來更多的方便,。

    本站是提供個人知識管理的網(wǎng)絡存儲空間,所有內(nèi)容均由用戶發(fā)布,,不代表本站觀點,。請注意甄別內(nèi)容中的聯(lián)系方式、誘導購買等信息,,謹防詐騙,。如發(fā)現(xiàn)有害或侵權內(nèi)容,請點擊一鍵舉報,。
    轉(zhuǎn)藏 分享 獻花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多