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

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

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

    笨笨的思想片斷

    零碎片斷,雜七雜八。
    posts - 25, comments - 79, trackbacks - 0, articles - 0

    Java中文&編碼問(wèn)題小結(jié)

    Posted on 2005-10-09 16:52 笨笨 閱讀(20546) 評(píng)論(12)  編輯  收藏 所屬分類: Java

    Java中文&編碼問(wèn)題小結(jié)

     

    笨笨

     

    Java字符編碼轉(zhuǎn)換過(guò)程說(shuō)明

     

    javacn_fig1.gif 

    常見問(wèn)題

     

    javacn_fig2.gif 

    JVM

    JVM啟動(dòng)后,JVM會(huì)設(shè)置一些系統(tǒng)屬性以表明JVM的缺省區(qū)域。

    user.language,user.region,file.encoding等。 可以使用System.getProperties()詳細(xì)查看所有的系統(tǒng)屬性。

     

    如在英文操作系統(tǒng)(UNIX)下,可以使用如下屬性定義強(qiáng)制指定JVM為中文環(huán)境 -Dclient.encoding.override=GBK -Dfile.encoding=GBK -Duser.language=zh -Duser.region=CN

     

    .java-->.class編譯

    說(shuō)明:一般javac根據(jù)當(dāng)前os區(qū)域設(shè)置,自動(dòng)決定源文件的編碼.可以通過(guò)-encoding強(qiáng)制指定.

     

    錯(cuò)誤可能:

    1 gbk編碼源文件在英文環(huán)境下編譯,javac不能正確轉(zhuǎn)換.曾見于java/jsp在英文unix. 檢測(cè)方法:\u4e00格式的漢字,繞開javac編碼,再在jvm,將漢字作為int打印,看值是否相等;或直接以UTF-8編碼打開.class文件,看看常量字符串是否正確保存漢字。

     

    文件讀寫

    外部數(shù)據(jù)如文件經(jīng)過(guò)讀寫和轉(zhuǎn)換兩個(gè)步驟,轉(zhuǎn)為jvm所使用字符。InputStream/OutputStream用于讀寫原始外部數(shù)據(jù),Reader/Writer執(zhí)行讀寫和轉(zhuǎn)換兩個(gè)步驟。

     

    1 文件讀寫轉(zhuǎn)換由java.io.Reader/Writer執(zhí)行;輸入輸出流 InputStream/OutputStream  處理漢字不合適,應(yīng)該首選使用Reader/Writer,如 FileReader/FileWriter

     

    2 FileReader/FileWriter使用JVM當(dāng)前編碼讀寫文件.如果有其它編碼格式,使用InputStreamReader/OutputStreamWriter

     

    3 PrintStream有點(diǎn)特殊,它自動(dòng)使用jvm缺省編碼進(jìn)行轉(zhuǎn)換。

     

     

    讀取.properties文件

    .propeties文件由Properties類以iso8859-1編碼讀取,因此不能在其中直接寫漢字,需要使用JDK native2ascii工具轉(zhuǎn)換漢字為\uXXXX格式。命令行:native2ascii –encoding GBK inputfile outputfile

     

    讀取XML文件

    1 XML文件讀寫同于文件讀寫,但應(yīng)注意確保XML頭中聲明如<? xml version=”1.0” encoding=”gb2312” ?>與文件編碼保持一致。

     

    2 javax.xml.SAXParser類接受InputStream作為輸入?yún)?shù),對(duì)于Reader,需要用org.xml.sax.InputSource包裝一下,再給SAXParser

     

    3 對(duì)于UTF-8編碼 XML,注意防止編輯器自動(dòng)加上\uFFFE BOM, xml parser會(huì)報(bào)告content is not allowed in prolog

     

     

    字節(jié)數(shù)組

    1 使用 new String(byteArray,encoding)   String.getBytes(encoding)  在字節(jié)數(shù)組和字符串之間進(jìn)行轉(zhuǎn)換

     

    也可以用ByteArrayInputStream/ByteArrayOutputStream轉(zhuǎn)為流后再用InputStreamReader/OutputStreamWriter轉(zhuǎn)換。

     

    錯(cuò)誤編碼的字符串(iso8859-1轉(zhuǎn)碼gbk)

    如果我們得到的字符串是由錯(cuò)誤的轉(zhuǎn)碼方式產(chǎn)生的,例如:對(duì)于gbk中文,由iso8859-1方式轉(zhuǎn)換,此時(shí)如果用調(diào)試器看到的字符串一般是 的樣子,長(zhǎng)度一般為文本的字節(jié)長(zhǎng)度,而非漢字個(gè)數(shù)。

     

    可以采用如下方式轉(zhuǎn)為正確的中文:

    text = new String( text.getBytes(“iso8859-1”),”gbk”);

     

    JDBC

    轉(zhuǎn)換過(guò)程由JDBC Driver執(zhí)行,取決于各JDBC數(shù)據(jù)庫(kù)實(shí)現(xiàn)。對(duì)此經(jīng)驗(yàn)尚積累不夠。

     

    1 對(duì)于ORACLE數(shù)據(jù)庫(kù),需要數(shù)據(jù)庫(kù)創(chuàng)建時(shí)指定編碼方式為gbk,否則會(huì)出現(xiàn)漢字轉(zhuǎn)碼錯(cuò)誤

    2 對(duì)于 SQL Server 2000 ,最好以nvarchar/nchar類型存放文本,即不存在中文/編碼轉(zhuǎn)換問(wèn)題。

    3 連接 Mysql,將 connectionString 設(shè)置成 encoding gb2312

     String connectionString  = "jdbc:mysql://localhost/test?useUnicode=true&characterEncoding=gb2312";

     

    WEB/Servlet/JSP

    1 對(duì)于JSP,確定頭部加上 <%@ page contentType="text/html;charset=gb2312"%>這樣的標(biāo)簽。

    2 對(duì)于Servlet,確定 設(shè)置setContentType (“text/html; charset=gb2312”),以上兩條用于使得輸出漢字沒有問(wèn)題。

    3 為輸出HTML head中加一個(gè) <meta http-equiv="Content-Type" content="text/html; charset=gb2312"> ,讓瀏覽器正確確定HTML編碼。

     

    4 Web應(yīng)用加一個(gè)Filter,確保每個(gè)Request明確調(diào)用setCharacterEncoding方法,讓輸入漢字能夠正確解析。

     

     

    import java.io.IOException;

    import javax.servlet.Filter;

    import javax.servlet.FilterChain;

    import javax.servlet.FilterConfig;

    import javax.servlet.ServletException;

    import javax.servlet.ServletRequest;

    import javax.servlet.ServletResponse;

    import javax.servlet.UnavailableException;

    import javax.servlet.http.HttpServletRequest;

     

    /**

     * Example filter that sets the character encoding to be used in parsing the

     * incoming request

     */

    public class SetCharacterEncodingFilter

        implements Filter {

      public SetCharacterEncodingFilter()

      {}

      protected boolean debug = false;

      protected String encoding = null;

      protected FilterConfig filterConfig = null;

      public void destroy() {

        this.encoding = null;

        this.filterConfig = null;

      }

     

      public void doFilter(ServletRequest request, ServletResponse response,

                           FilterChain chain) throws IOException, ServletException {

    //    if (request.getCharacterEncoding() == null)

    //    {

    //      String encoding = getEncoding();

    //      if (encoding != null)

    //        request.setCharacterEncoding(encoding);

    //

    //    }

          request.setCharacterEncoding(encoding);

          if ( debug ){

            System.out.println( ((HttpServletRequest)request).getRequestURI()+"setted to "+encoding );

          }

        chain.doFilter(request, response);

      }

     

      public void init(FilterConfig filterConfig) throws ServletException {

        this.filterConfig = filterConfig;

        this.encoding = filterConfig.getInitParameter("encoding");

        this.debug = "true".equalsIgnoreCase( filterConfig.getInitParameter("debug") );

      }

     

      protected String getEncoding() {

        return (this.encoding);

      }

    }

     

     

    web.xml中加入:

     

      <filter>

        <filter-name>LocalEncodingFilter</filter-name>

        <display-name>LocalEncodingFilter</display-name>

        <filter-class>com.ccb.ectipmanager.request.SetCharacterEncodingFilter</filter-class>

        <init-param>

          <param-name>encoding</param-name>

          <param-value>gb2312</param-value>

        </init-param>

        <init-param>

          <param-name>debug</param-name>

          <param-value>false</param-value>

        </init-param>

      </filter>

     

       <filter-mapping>

        <filter-name>LocalEncodingFilter</filter-name>

        <url-pattern>/*</url-pattern>

      </filter-mapping>

     

    5 用于Weblogicvedor-specific):

    其一:web.xml里加上如下腳本:

    <context-param>

      <param-name>weblogic.httpd.inputCharset./*</param-name>

      <param-value>GBK</param-value>

    </context-param>

    其二(可選)在weblogic.xml里加上如下腳本:

    <charset-params>

      <input-charset>

          <resource-path>/*</resource-path>

          <java-charset-name>GBK</java-charset-name>

      </input-charset>

    </charset-params>

     

    SWING/AWT/SWT

    對(duì)于SWING/AWTJava會(huì)有些缺省字體如Dialog/San Serif,這些字體到系統(tǒng)真實(shí)字體的映射在$JRE_HOME/lib/font.properties.XXX文件中指定。排除字體顯示問(wèn)題時(shí),首先需要確定JVM的區(qū)域?yàn)?/SPAN>zh_CN,這樣font.properties.zh_CN文件才會(huì)發(fā)生作用。對(duì)于 font.properties.zh_CN , 需要檢查是否映射缺省字體到中文字體如宋體。

     

    Swing中,Java自行解釋TTF字體,渲染顯示;對(duì)于AWT,SWT顯示部分交由操作系統(tǒng)。首先需要確定系統(tǒng)裝有中文字體。

     

    1 漢字顯示為,一般為顯示字體沒有使用中文字體,因?yàn)?/SPAN>Java對(duì)于當(dāng)前字體顯示不了的字符,不會(huì)像Windows一樣再采用缺省字體顯示。

    2 部分不常見漢字不能顯示,一般為顯示字庫(kù)中漢字不全,可以換另外的中文字體試試。

    3 對(duì)于AWT/SWT,首先確定JVM運(yùn)行環(huán)境的區(qū)域設(shè)置為中文,因?yàn)榇颂幵O(shè)計(jì)JVM與操作系統(tǒng)api調(diào)用的轉(zhuǎn)換問(wèn)題,再檢查其它問(wèn)題。

     

    JNI

    JNIjstringUTF-8編碼給我們,需要我們自行轉(zhuǎn)為本地編碼。對(duì)于Windows,可以采用WideCharToMultiByte/MultiByteToWideChar函數(shù)進(jìn)行轉(zhuǎn)換,對(duì)于Unix,可以采用iconv庫(kù)。

     

    這里從SUN jdk 1.4 源代碼中找到一段使用jvm String 對(duì)象的getBytes的轉(zhuǎn)換方式,相對(duì)簡(jiǎn)單和跨平臺(tái),不需要第三方庫(kù),但速度稍慢。函數(shù)原型如下:

     

    /* Convert between Java strings and i18n C strings */

    JNIEXPORT jstring

    NewStringPlatform(JNIEnv *env, const char *str);

     

    JNIEXPORT const char *

    GetStringPlatformChars(JNIEnv *env, jstring jstr, jboolean *isCopy);

     

    JNIEXPORT jstring JNICALL

    JNU_NewStringPlatform(JNIEnv *env, const char *str);

     

    JNIEXPORT const char * JNICALL

    JNU_GetStringPlatformChars(JNIEnv *env, jstring jstr, jboolean *isCopy);

     

    JNIEXPORT void JNICALL

    JNU_ReleaseStringPlatformChars(JNIEnv *env, jstring jstr, const char *str);

     

     

    附件jni_util.h,jni_util.c

     

     

    TUXEDO/JOLT

    JOLT對(duì)于傳遞的字符串需要用如下進(jìn)行轉(zhuǎn)碼

    new String(ls_tt.getBytes("GBK"),"iso8859-1")

     

    對(duì)于返回的字符串

    new String(error_message.getBytes("iso8859-1"),"GBK");

    jolt 的系統(tǒng)屬性 bea.jolt.encoding不應(yīng)該設(shè)置,如果設(shè)置,JSH會(huì)報(bào)告說(shuō)錯(cuò)誤的協(xié)議.

     

     

    JDK1.4/1.5新增部分

    字符集相關(guān)類(Charset/CharsetEncoder/CharsetDecoder)

    jdk1.4開始,對(duì)字符集的支持在java.nio.charset包中實(shí)現(xiàn)。

     

    常用功能:

    1 列出jvm所支持字符集:Charset.availableCharsets()

    2 能否對(duì)看某個(gè)Unicode字符編碼,CharsetEncoder.canEncode()

     

    Unicode Surrogate/CJK EXT B

    Unicode 范圍一般所用為\U0000-\UFFFF范圍,jvm使用1個(gè)char就可以表示,對(duì)于CJK EXT B區(qū)漢字,范圍大于\U20000,則需要采用2個(gè)char方能表示,此即Unicode Surrogate。這2個(gè)char的值范圍 落在Character.SURROGATE 區(qū)域內(nèi),用Character.getType()來(lái)判斷。

     

    jdk 1.4尚不能在Swing中正確處理surrogate區(qū)的Unicode字符,jdk1.5可以。對(duì)于CJK EXT B區(qū)漢字,目前可以使用的字庫(kù)為宋體-方正超大字符集”,Office安裝。

     

    常見問(wèn)題

    JVM下,用System.out.println不能正確打印中文,顯示為???

    System.out.printlnPrintStream,它采用jvm缺省字符集進(jìn)行轉(zhuǎn)碼工作,如果jvm的缺省字符集為iso8859-1,則中文顯示會(huì)有問(wèn)題。此問(wèn)題常見于Unix下,jvm的區(qū)域沒有明確指定的情況。

     

    在英文UNIX環(huán)境下,System.out.println能夠正確打印漢字,但是內(nèi)部處理錯(cuò)誤

    可能是漢字在輸入轉(zhuǎn)換時(shí),就沒有正確轉(zhuǎn)碼:

    gbk文本à(iso8859-1轉(zhuǎn)碼)àjvm char(iso8859-1編碼漢字)à (iso8859-1轉(zhuǎn)碼)à輸出。

    gbk漢字經(jīng)過(guò)兩次錯(cuò)誤轉(zhuǎn)碼,原封不動(dòng)的被傳遞到輸出,但是在jvm中,并未以正確的unicode編碼表示,而是以一個(gè)漢字字節(jié)一個(gè)char的方式表示,從而導(dǎo)致此類錯(cuò)誤。

     

     

    GB2312-80GBKGB18030-2000 漢字字符集

     

    GB2312-80 是在國(guó)內(nèi)計(jì)算機(jī)漢字信息技術(shù)發(fā)展初始階段制定的,其中包含了大部分常用的一、二級(jí)漢字,和 9 區(qū)的符號(hào)。該字符集是幾乎所有的中文系統(tǒng)和國(guó)際化的軟件都支持的中文字符集,這也是最基本的中文字符集。其編碼范圍是高位0xa10xfe,低位也是 0xa1-0xfe;漢字從 0xb0a1 開始,結(jié)束于 0xf7fe

     

    GBK GB2312-80 的擴(kuò)展,是向上兼容的。它包含了 20902 個(gè)漢字,其編碼范圍是 0x8140-0xfefe,剔除高位 0x80 的字位。其所有字符都可以一對(duì)一映射到 Unicode 2.0,也就是說(shuō) JAVA 實(shí)際上提供了 GBK 字符集的支持。這是現(xiàn)階段 Windows 和其它一些中文操作系統(tǒng)的缺省字符集,但并不是所有的國(guó)際化軟件都支持該字符集,感覺是他們并不完全知道 GBK 是怎么回事。值得注意的是它不是國(guó)家標(biāo)準(zhǔn),而只是規(guī)范。隨著 GB18030-2000國(guó)標(biāo)的發(fā)布,它將在不久的將來(lái)完成它的歷史使命。

     

    GB18030-2000(GBK2K) GBK 的基礎(chǔ)上進(jìn)一步擴(kuò)展了漢字,增加了藏、蒙等少數(shù)民族的字形。GBK2K 從根本上解決了字位不夠,字形不足的問(wèn)題。它有幾個(gè)特點(diǎn),

     

    它并沒有確定所有的字形,只是規(guī)定了編碼范圍,留待以后擴(kuò)充。

    編碼是變長(zhǎng)的,其二字節(jié)部分與 GBK 兼容;四字節(jié)部分是擴(kuò)充的字形、字位,其編碼范圍是首字節(jié) 0x81-0xfe、二字節(jié)0x30-0x39、三字節(jié) 0x81-0xfe、四字節(jié)0x30-0x39

     

    UTF-8/UTF-16/UTF-32

     

    UTF,即Unicode Transformer Format,是Unicode代碼點(diǎn)(code point)的實(shí)際表示方式,按其基本長(zhǎng)度所用位數(shù)分為UTF-8/16/32。它也可以認(rèn)為是一種特殊的外部數(shù)據(jù)編碼,但能夠與Unicode代碼點(diǎn)做一一對(duì)應(yīng)。

     

    UTF-8是變長(zhǎng)編碼,每個(gè)Unicode代碼點(diǎn)按照不同范圍,可以有1-3字節(jié)的不同長(zhǎng)度。

    UTF-16長(zhǎng)度相對(duì)固定,只要不處理大于\U200000范圍的字符,每個(gè)Unicode代碼點(diǎn)使用16位即2字節(jié)表示,超出部分使用兩個(gè)UTF-164字節(jié)表示。按照高低位字節(jié)順序,又分為UTF-16BE/UTF-16LE

    UTF-32長(zhǎng)度始終固定,每個(gè)Unicode代碼點(diǎn)使用32位即4字節(jié)表示。按照高低位字節(jié)順序,又分為UTF-32BE/UTF-32LE

     

    UTF編碼有個(gè)優(yōu)點(diǎn),即盡管編碼字節(jié)數(shù)不等,但是不像gb2312/gbk編碼一樣,需要從文本開始尋找,才能正確對(duì)漢字進(jìn)行定位。在UTF編碼下,根據(jù)相對(duì)固定的算法,從當(dāng)前位置就能夠知道當(dāng)前字節(jié)是否是一個(gè)代碼點(diǎn)的開始還是結(jié)束,從而相對(duì)簡(jiǎn)單的進(jìn)行字符定位。不過(guò)定位問(wèn)題最簡(jiǎn)單的還是UTF-32,它根本不需要進(jìn)行字符定位,但是相對(duì)的大小也增加不少。

     

     

    關(guān)于GCJ JVM

    GCJ并未完全依照sun jdk的做法,對(duì)于區(qū)域和編碼問(wèn)題考慮尚不夠周全。GCJ啟動(dòng)時(shí),區(qū)域始終設(shè)為en_US,編碼也缺省為iso8859-1。但是可以用Reader/Writer做正確編碼轉(zhuǎn)換。

     

     

    Feedback

    # re: Java中文&編碼問(wèn)題小結(jié)  回復(fù)  更多評(píng)論   

    2005-10-09 23:10 by coordinator
    真是全面
    收藏了

    # re: Java中文&編碼問(wèn)題小結(jié)  回復(fù)  更多評(píng)論   

    2005-10-10 19:50 by martin xus
    thx :)

    # re: Java中文&編碼問(wèn)題小結(jié)  回復(fù)  更多評(píng)論   

    2005-11-15 10:52 by zhaowd2001@yahoo.com
    不錯(cuò),支持!做項(xiàng)目就需要這樣的知識(shí)。

    # re: Java中文&編碼問(wèn)題小結(jié)  回復(fù)  更多評(píng)論   

    2005-12-08 18:17 by 老貓
    真正的好文章

    # re: Java中文&編碼問(wèn)題小結(jié)  回復(fù)  更多評(píng)論   

    2006-01-18 16:15 by boris
    說(shuō)的好

    # re: Java中文&編碼問(wèn)題小結(jié)  回復(fù)  更多評(píng)論   

    2006-03-14 18:08 by 小飛俠
    樓主總結(jié)的很全啊 看了以后感觸很深~~非常感謝!

    # re: Java中文&編碼問(wèn)題小結(jié)  回復(fù)  更多評(píng)論   

    2006-03-16 10:52 by bbdos
    探討下啊

    # re: Java中文&編碼問(wèn)題小結(jié)  回復(fù)  更多評(píng)論   

    2006-03-16 10:55 by bbdos
    --字符集編碼

    1. 概述

    本文主要包括以下幾個(gè)方面:編碼基本知識(shí),java,系統(tǒng)軟件,url,工具軟件等。

    在下面的描述中,將以"中文"兩個(gè)字為例,經(jīng)查表可以知道其GB2312編碼是"d6d0 cec4",Unicode編碼為"4e2d 6587",UTF編碼就是"e4b8ad e69687"。注意,這兩個(gè)字沒有iso8859-1編碼,但可以用iso8859-1編碼來(lái)"表示"。

    2. 編碼基本知識(shí)

    最早的編碼是iso8859-1,和ascii編碼相似。但為了方便表示各種各樣的語(yǔ)言,逐漸出現(xiàn)了很多標(biāo)準(zhǔn)編碼,重要的有如下幾個(gè)。(文章詳細(xì)內(nèi)容請(qǐng)?jiān)L問(wèn)以下鏈接 http://china.eceel.com/article/study_for_character_encoding_java.htm

    # re: Java中文&編碼問(wèn)題小結(jié)  回復(fù)  更多評(píng)論   

    2006-03-16 11:11 by 笨笨
    文章瀏覽過(guò)了。
    東西挺多,但是覺得有點(diǎn)亂。
    還有關(guān)于 Unicode 部分,看起來(lái)主要說(shuō)的是 UTF-8編碼,UTF-16/32 甚少涉及。

    # re: Java中文&編碼問(wèn)題小結(jié)  回復(fù)  更多評(píng)論   

    2007-05-25 16:29 by loocky
    說(shuō)實(shí)話我感覺很亂

    # re: Java中文&編碼問(wèn)題小結(jié)  回復(fù)  更多評(píng)論   

    2011-06-21 11:38 by 白一梓
    求附件下載,謝謝

    # re: Java中文&編碼問(wèn)題小結(jié)  回復(fù)  更多評(píng)論   

    2012-05-30 19:43 by ting.yang
    寫出這樣的文章已經(jīng)是很有才了!!
    主站蜘蛛池模板: 亚洲午夜精品一区二区| 亚洲娇小性色xxxx| 亚洲精品无码人妻无码| 久久久久久av无码免费看大片| 曰批全过程免费视频播放网站| 国产成人免费a在线视频色戒| 国产成人亚洲精品青草天美| 亚洲色偷偷综合亚洲av78| 9久热精品免费观看视频| 久久综合AV免费观看| 亚洲综合色在线观看亚洲| 亚洲理论片在线中文字幕| 色老头综合免费视频| 亚洲精品视频免费在线观看| 俄罗斯极品美女毛片免费播放| 亚洲AV区无码字幕中文色| 色婷婷六月亚洲综合香蕉| 亚洲精品免费在线观看| mm1313亚洲国产精品美女| 亚洲图片中文字幕| 国产无限免费观看黄网站| 成人无遮挡裸免费视频在线观看| 亚洲日韩中文字幕在线播放| 亚洲 欧洲 日韩 综合在线| a级毛片在线免费| 国产中文字幕免费| 亚洲人成黄网在线观看| 日韩免费高清播放器| 国产免费一区二区三区VR| 亚洲国产成人九九综合| A级毛片高清免费视频在线播放| 全免费a级毛片免费看无码| 91亚洲va在线天线va天堂va国产| 九一在线完整视频免费观看| 成年轻人网站色免费看| 亚洲欧洲第一a在线观看| 产传媒61国产免费| 暖暖免费高清日本一区二区三区| 亚洲色大成网站www永久| 日韩精品无码免费专区网站| 亚洲国产成人影院播放|