<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    [收藏]Java中文問題的一般解決辦法

    Posted on 2006-03-30 05:14 ikingqu 閱讀(240) 評論(0)  編輯  收藏 所屬分類: JavaSE&JavaEE

    漢字編碼的常識

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


    事實上,Java的中文問題都是由于Java應用所采用的缺省編碼格式與目標或者應用所要讀入字符的編碼格式不同而造成的(具體參見文獻1)。對于如何解決Java的中文問題,通常有四種方法:

    1) 選擇JDK的中文本地化版本。盡管Java2 JDK的中文本地化版本(http://java.sun.com/products/jdk/1.2/chinesejdk.html)并不是一個官方的版本,Sun公司也沒有承諾會對該本地化版本進行升級,但其仍不失為一個Java中文問題的解決方案。

    2) 選擇合適的編譯參數。對于Java的國際版本來講,我們也可以在編譯Java應用的時候通過指定確定的編碼機制來實現其編譯結果對中文的支持。例如,對于需要支持繁體中文和簡體中文應用可以通過javac -encoding big5 sourcefile.java 和javac -encoding gb2312 sourcefile.java來編譯源程序。

    3) 通過編程的方式實現字符編碼的轉換代碼。通過編程的方式來解決Java的中文問題,已經成為了一種較為普遍的做法。下面就是一種最常見的字符編碼轉換函數,其將字符的編碼格式轉換為中文Windows系統的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) 定義字符輸出集。對于JSP應用,我們可以通過<%@ page contentType="text/html; charset=GBK" %>或<%@ page contentType="text/html; charset=GB2312" %>來定義JSP頁面的字符輸出集。當然,我們也可以通過HTML的標記<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=gb2312">來定義字符的輸出集。

    分析的原則

    總的說來,所有解決Java中文處理的方法都不是很復雜。相反的是,由于Java技術特別是J2EE技術涉及的內容繁多,各種Web服務器、應用服務器以及JDBC數據庫驅動等參差不齊,所以如何正確而及時的發現應用的中文處理問題則變得相對復雜的多。那么我們如何來發現這些問題呢?

    通常,Java處理中文時所產生的問題都是由于用戶的Java應用所采用的缺省編碼格式與目標或者應用所要讀入字符的編碼格式不同而造成的,而引起這些不同的一個主要原因就是用戶的Java應用與其它應用進行了編碼格式不匹配的數據交換(包括直接或間接的數據輸入、輸出)。所以,為了及時發現問題,我們可以由這一點入手,根據以下的原則對應用進行分析:

    1. 注意字符變量情況。由于變量的字符編碼形式較為隱蔽,多次變量間數值的改變和運算可能會引起字符集的改變;在變量與頁面所提交數據的各種操作中,較容易發生不同編碼格式字符進行運算的情況。
    2. 注意任何形式的字符讀入與輸出。之所以要提到任何形式,是因為Java應用大多數都是作為網絡應用開發的,所以與其它語言的應用相比,Java應用需要面對網絡世界各種各樣的字符數據交換形式。例如各種表單的數據提交,URL形式的數據讀入,經過加密運算的字符數據交換,網頁控件選擇結果的輸入,控件內容的的顯示(如List控件)等等。
    3. 小心使用第三方的組件和應用。由于第三方組件和應用的實現是非透明的,所以一般情況下,我們很難判斷這些組件或驅動的缺省編碼格式是什么,也無法對其進行控制。因此,在使用它們所提供的接口函數進行數據交換的時候要特別注意,如果確實出現中文無法正確處理情況,應首先檢查我們自己的代碼并調整相關代碼以適應這些接口,因為這些組件或者應用基本上不會提供調整編碼機制的接口。必要時,我們可能需要采用其它可替換的組件或者應用。
    4. 注意被請求對象所含有的數據輸入與輸出。這是非常隱蔽的一類情況,當我們的應用以對象的方式(例如序列化的對象)進行交互時,如果這個對象內部含有字符數據的處理過程,或者含有某些數據的輸入、輸出,甚至是拋出一段用中文注解的異常,都可能出現中文無法正確顯示等問題。由于這些行為往往被封裝在對象中,所以我們在編寫程序時,很容易忽略這種可能情況。并且這種情況帶有一定的不可預見性,例如我們可能不清楚這個對象會在什么時候拋出什么樣的異常,所以這時我們就需要做一定的測試工作。
    5. 注意數據庫的數據訪問過程。Java通過JDBC與數據庫建立連接。對于JDBC驅動程序來說,由于目前大部分的JDBC驅動程序并不是針對中文系統而設計的(中文數據大都采用ISO-8859-1編碼方式),所以一般情況下在數據讀寫過程中往往都需要字符編碼的轉化。但是我們仍建議用戶在使用這些JDBC驅動時,仔細閱讀它的說明。如果確實無法弄清JDBC字符數據的編碼到底是什么,我們的建議是做一些必要的測試。例如下面是一組在簡體中文Win2000平臺下,采用Weblogic 6.0所提供的JDBC驅動從MS SQL Server2000中正確讀入中文字符的代碼(例子中進行了字符運算):
      ????
      Class.forName(
      "weblogic.jdbc.mssqlserver4.Driver").newInstance();
      ??????conn?
      =?myDriver.connect("jdbc:weblogic:mssqlserver4",?props);
      ??????conn.setCatalog(
      "labmanager");
      ?????Statement?st?
      =?conn.createStatement();
      ????????
      //execute?a?query
      ????String??testStr;
      String?testTempStr?
      =?new?String()?;
      ????????testStr?
      =?new?String(testTempStr.getBytes("ISO-8859-1"));//編碼轉化
      ????DatabaseMetaData?DBMetaData?=conn.getMetaData();
      ????ResultSet?rs?
      =?DBMetaData.getTables(null,?null,null,new?String[]{"TABLE"}?);
      ????
      while?(rs.next()){
      ????????
      for(int?j=1;?j<=rs.getMetaData().getColumnCount();?j++){
      testStr?
      =?testStr?+String(rs.getObject(j).toString().getBytes("ISO-8859-1"));
      ????????????}

      ????????}
    6. 然而,需要注意的是,不同的JDBC驅動對相同的數據庫的支持并不同,而同一類JDBC驅動對不同的??數據庫的支持也不相同,也就是說我們的字符轉化代碼在JDBC驅動改變甚至是版本變化情況下都有可能無法正確工作。例如對于上面的例子,在同樣的環境下改用i-net 的Una 2000 Driver Version 2.03 for MS SQL Server時,是無法正確處理中文的。原因很簡單,這個JDBC驅動本身支持的就是GBK的編碼機制,所以根本就不需要做任何的編碼轉化。?
    7. ?必要的測試。由于Java中文問題的產生隨著Web服務器,瀏覽器,運行環境和開發工具的不同都可能發生變化,所以為了更好的避免問題的發生,我們必須作一些針對性的測試。另外,在我們確實無法通過分析來確定Java的中文處理問題是否可能發生的情況下或者無法知道問題的發生是由于哪個環節(是Web服務器,瀏覽器還是JDBC數據驅動等等)引起的時候,測試工作則變得非常重要。并且我們可能需要較為全面的測試,例如對Web服務器,瀏覽器和JDBC數據驅動等都要做測試,這樣有利于我們找出那些隱藏在多個環節協調過程中所產生的問題。


    Java 的基本類也可能存在問題。由于國際化的工作并不是在國內完成的,所以在這些基本類發布之前,沒有經過嚴格的測試,所以對中文字符的支持并不像 Java Soft 所聲稱的那樣完美。前不久,我的一位技術上的朋友發信給我說,他終于找到了 Java Servlet 中文問題的根源。兩周以來,他一直為 Java Servlet 的中文問題所困擾,因為每面對一個含有中文字符的字符串都必須進行強制轉換才能夠得到正確的結果(這好象是大家公認的唯一的解決辦法)。后來,他確實不想如此繼續安分下去了,因為這樣的事情確實不應該是高級程序員所要做的工作,他就找出 Servlet 解碼的源代碼進行分析,因為他懷疑問題就出在解碼這部分。經過四個小時的奮斗,他終于找到了問題的根源所在。原來他的懷疑是正確的, Servlet 的解碼部分完全沒有考慮雙字節,直接把 %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中文問題詳解
    http://www.cn-java.com/target/news.php?news_id=210
    關于Java中文問題的幾條分析原則http://www-900.ibm.com/developerWorks/cn/java/l-javachinese/index.shtml
    全方位解決xml中文問題http://www.csdn.net/develop/read_article.asp?id=18901
    servlet 中的漢字編碼問題http://www-900.ibm.com/developerWorks/cn/java/jsp_dbcsz/index.shtml
    Java程序的國際化和本地化介紹http://www-900.ibm.com/developerWorks/cn/java/joy-i18n/index.shtml
    Java 編程技術中漢字問題的分析及解決http://www-900.ibm.com/developerWorks/cn/java/java_chinese/index.shtml
    Unicode專題http://www-900.ibm.com/developerWorks/cn/theme/unicode.shtml
    這里也有篇專家寫的文章:
    http://www.javaworld.com/javaworld/jw-04-2004/jw-0419-multibytes.html

    posts - 4, comments - 5, trackbacks - 0, articles - 60

    Copyright © ikingqu

    主站蜘蛛池模板: 一级视频免费观看| 老外毛片免费视频播放| 久久精品国产这里是免费| 国产精品无码免费播放| 亚洲国产综合专区电影在线| 一级毛片免费在线观看网站| 亚洲男人的天堂一区二区| 黄色网页在线免费观看| 亚洲午夜福利717| 七色永久性tv网站免费看| 亚洲AV无码精品色午夜果冻不卡| 亚洲aⅴ天堂av天堂无码麻豆| 91在线视频免费91| 91在线亚洲综合在线| 日本免费人成黄页网观看视频 | 三年片在线观看免费大全| 亚洲综合无码一区二区痴汉| 最新猫咪www免费人成| 国产成人综合亚洲绿色| 亚洲熟妇av一区二区三区| 久久er国产精品免费观看2| 亚洲日韩区在线电影| 影音先锋在线免费观看| 青青视频免费在线| 国产精品亚洲аv无码播放| 成年人免费的视频| 看亚洲a级一级毛片| 亚洲韩国精品无码一区二区三区| 99xxoo视频在线永久免费观看| 日本亚洲免费无线码 | 又硬又粗又长又爽免费看| 亚洲av伊人久久综合密臀性色| 精品国产sm捆绑最大网免费站| 亚洲欧美日韩中文无线码| www.91亚洲| 精品一区二区三区无码免费视频| 亚洲一本一道一区二区三区| 亚洲伊人久久成综合人影院| 91热久久免费精品99| 色婷婷亚洲一区二区三区| 亚洲精品成人av在线|