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

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

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

    卓凡

     

    (轉(zhuǎn))Java中文處理學(xué)習(xí)筆記——Hello Unicode

    Java中文處理學(xué)習(xí)筆記——Hello Unicode

    作者: 車東 Email: chedongATbigfoot.com/chedongATchedong.com

    寫于:2002/07 最后更新: 10/26/2004 10:25:01

    版權(quán)聲明:可以任意轉(zhuǎn)載,轉(zhuǎn)載時(shí)請(qǐng)務(wù)必以超鏈接形式標(biāo)明文章原始出處和作者信息及本聲明
    http://www.chedong.com/tech/hello_unicode.html

    關(guān)鍵詞:linux java mutlibyte encoding locale i18n i10n chinese  ISO-8859-1 GB2312 BIG5 GBK UNICODE

    內(nèi)容摘要:

    不知道你有沒有這樣的感受:為什么PHP很少有亂碼問題而用Java做WEB應(yīng)用卻這么麻煩呢?為什么在Google上能用簡(jiǎn)體中文查到繁體中文,甚至日文的結(jié)果?而且用Google的時(shí)候發(fā)現(xiàn)它居然能自動(dòng)根據(jù)我使用瀏覽器的語(yǔ)言選擇自動(dòng)調(diào)出中文界面?

    很多國(guó)際化應(yīng)用的讓我理解了這么一個(gè)道理:Unicode是為更方便的做國(guó)際化應(yīng)用設(shè)計(jì)的,而Java核心的字符是基于UNICODE的,這一機(jī)制 為應(yīng)用提供了對(duì)中文“字”的控制(而不是字節(jié))。但如果不仔細(xì)理解其中的規(guī)范,這種自由反而會(huì)成為累贅,從而導(dǎo)致更多的亂碼問題:

    1. 關(guān)于字符集的一些基本概念;
    2. 試驗(yàn)1:顯示系統(tǒng)的環(huán)境設(shè)置和支持的編碼方式;
    3. 試驗(yàn)2:系統(tǒng)缺省編碼方式對(duì)Java應(yīng)用的輸入輸出影響;
    4. 試驗(yàn)3:在WEB應(yīng)用中輸出和輸出中的字符集問題;

    關(guān)于字符集的準(zhǔn)備知識(shí):
    ISO-8859-1 GB2312 BIG5 GBK GB18030 UNICODE 為什么會(huì)有這么多字符集編碼方式?

    注意:以下說明不是嚴(yán)格定義,一些比喻僅作為方便理解使用。

    假設(shè)一個(gè)字符就是棋盤上的一個(gè)棋子,有其固定的坐標(biāo),如果需要區(qū)別所有的字符,就需要有足夠的棋格容納不同的“字符”。 

    英文和歐洲其他語(yǔ)言的單字節(jié)字符集(SingleByte Charsets):
    首先對(duì)于ISO-8859系列的字符集都想象成一個(gè):2^8 = 16 * 16 = 256個(gè)格子的棋盤,這樣所有的西文字符(英文)用這樣一個(gè)16×16的坐標(biāo)系就基本可以覆蓋全了。而英文實(shí)際上只用其中小于128(\x80)的部分就夠了。利用大于128部分的空間的不同定義規(guī)則形成了真對(duì)其他歐洲語(yǔ)言的擴(kuò)展字符集:ISO-8859-2 ISO-8859-4等……

    ISO-8859-1
    ISO-8859-7
    其他語(yǔ)言
    英文 其他西歐字符
      ōē
    英文 希臘字符
      μγ
    英文 其他單字節(jié)
      字符集


    GB2312 BIG5 SJIS等多字節(jié)字符集(MultiByte Charsets):

    對(duì)于亞洲語(yǔ)言來說:漢字這么多,用這么一個(gè)256格的小棋盤肯定放不下,所以要區(qū)別成千上萬(wàn)的漢字解決辦法就是用2個(gè)字節(jié)(坐標(biāo))來定位一個(gè)“字”在棋盤上的位置,將以上規(guī)則做一個(gè)擴(kuò)展:

    • 如果第1個(gè)字符是小于128(\x80)的仍和英文字符集編碼方式保持兼容;
    • 如果第1個(gè)字符是大于128(\x80)的,就當(dāng)成是漢字的第1個(gè)字節(jié),這個(gè)自己和后面緊跟的1個(gè)字節(jié)組成一個(gè)漢字;

    其結(jié)果相當(dāng)于在位于128以上的小棋格里每個(gè)小棋格又劃分出了一個(gè)16×16的小棋盤。這樣一個(gè)棋盤中的格子數(shù)(可能容納的字符數(shù))就變成了128 + 128 * 256。按照類似的方式有了簡(jiǎn)體中文的GB2312標(biāo)準(zhǔn),繁體中文的BIG5字符集和日文的SJIS字符集等,GB2312字符集包含大約有六仟多個(gè)常用簡(jiǎn)體漢字。

    簡(jiǎn)體中文
    日文SJIS
    繁體中文
    英文 簡(jiǎn)
     
     
     
     
    英文
     
         
       
    英文

     
       

    由此可以看出,所有這些從ASCII擴(kuò)展式的編碼方式中:英文部分都是兼容的,但擴(kuò)展部分的編碼方式是不兼容的,雖然很多字在3種體系中寫法一致 (比如“中文”這2個(gè)字)但在相應(yīng)字符集中的坐標(biāo)不一致,所以GB2312編寫的頁(yè)面用BIG5看就變得面目全非了。而且有時(shí)候經(jīng)常在瀏覽其他非英語(yǔ)國(guó)家 的頁(yè)面時(shí)(比如包含有德語(yǔ)的人名時(shí))經(jīng)常出現(xiàn)奇怪的漢字,其實(shí)就是擴(kuò)展位的編碼沖突造成的。

    我把GBK和GB18030理解成一個(gè)小UNICODE:GBK字符集是GB2312的擴(kuò)展(K),GBK里大約有貳萬(wàn)玖仟多個(gè)字符,除了保持和 GB2312兼容外,繁體中文字,甚至連日文的假名字符也能顯示。而GB18030-2000則是一個(gè)更復(fù)雜的字符集,采用變長(zhǎng)字節(jié)的編碼方式,能夠支持 更多的字符。關(guān)于漢字的編碼方式比較詳細(xì)的定義規(guī)范可以參考:
    http://www.unihan.com.cn/cjk/ana17.htm

    ASCII(英文) ==> 西歐文字 ==> 東歐字符集(俄文,希臘語(yǔ)等) ==> 東亞字符集(GB2312 BIG5 SJIS等)==> 擴(kuò)展字符集GBK GB18030這個(gè)發(fā)展過程基本上也反映了字符集標(biāo)準(zhǔn)的發(fā)展過程,但這么隨著時(shí)間的推移,尤其是互聯(lián)網(wǎng)讓跨語(yǔ)言的信息的交互變得越來越多的時(shí)候,太多多針 對(duì)本地語(yǔ)言的編碼標(biāo)準(zhǔn)的出現(xiàn)導(dǎo)致一個(gè)應(yīng)用程序的國(guó)際化變得成本非常高。尤其是你要編寫一個(gè)同時(shí)包含法文和簡(jiǎn)體中文的文檔,這時(shí)候一般都會(huì)想到要是用一個(gè)通 用的字符集能夠顯示所有語(yǔ)言的所有文字就好了,而且這樣做應(yīng)用也能夠比較方便的國(guó)際化,為了達(dá)到這個(gè)目標(biāo),即使應(yīng)用犧牲一些空間和程序效率也是非常值得 的。UNICODE就是這樣一個(gè)通用的解決方案。

    UNICODE雙字節(jié)字符集
    所以你可以把UNICODE想象成這樣:讓所有的字符(包括英文)都用2個(gè)字節(jié)(2個(gè)8位)表示,這樣就有了一個(gè)2^(8*2) = 256 * 256 = 65536個(gè)格子的大棋盤。在這個(gè)棋盤中,這樣中(簡(jiǎn)繁)日韓(還包括越南)文字作為CJK字符集都放在一定的區(qū)位內(nèi),為了減少重復(fù),各種語(yǔ)言中寫法一樣的字共享一個(gè)“棋格”。詳細(xì)的區(qū)位見附錄A

    Unicode:(DoubleByte Charsets)

    西 C中  
    J日  
    K韓   語(yǔ)
       

     

    什么還要有UTF-8?畢竟互聯(lián)網(wǎng)70%以上的信息仍然是英文。如果連英文都用2個(gè)字節(jié)存取(UCS-2),空間浪費(fèi)不就太多了?所謂UTF-8就是這樣一個(gè)為了提高英文存取效率的字符集轉(zhuǎn)換格式:Unicode Transformation Form 8-bit form。用UTF-8,UNICODE的2字節(jié)字符用變長(zhǎng)個(gè)(1-3個(gè)字節(jié))表示:

    1. 對(duì)英文,仍然和ASCII一樣用1個(gè)字節(jié)表示,這個(gè)字節(jié)的值小于128(\x80);
    2. 對(duì)其他語(yǔ)言的用一個(gè)值位于128-256之間的字節(jié)開始,再加后面緊跟的2個(gè)字節(jié)表示,一個(gè)字符一共是3個(gè)字節(jié);

    因此,在應(yīng)用中程序處理過程中所有字符都是16位(雙字節(jié)),但在存取轉(zhuǎn)換成字節(jié)流時(shí)使用UTF-8格式轉(zhuǎn)換,對(duì)于英文字符來說和原來用ASCII方式存取時(shí)相比大小仍然是一樣的,而對(duì)中文來說和原來的GB2312編碼方式相比,大小為:(3字節(jié)/2字節(jié))=1.5倍

    小節(jié):

    假設(shè)英文字符集是一個(gè)16×16的棋盤,么其他語(yǔ)言的字符集就是把高位區(qū)重新分割的(> 128)的中等棋盤,多種字符集之間互不兼容而UNICODE本身就相當(dāng)于一個(gè)256×256的大棋盤,通過一定規(guī)則將英文和其他所有語(yǔ)言的字符都包含在內(nèi)。

    試驗(yàn)1:操作系統(tǒng)語(yǔ)言環(huán)境設(shè)置對(duì)Java應(yīng)用缺省編碼方式的影響

    為了了解Java應(yīng)用的編碼處理的機(jī)制,首先要了解操作系統(tǒng)對(duì)JVM缺省編碼方式的影響,因此我做了一個(gè)Env.java,用于打印顯示不同系統(tǒng)下JVM的屬性和系統(tǒng)支持的LOCALE。程序很簡(jiǎn)單:

    /*
    * Copyright (c) 2002 Email: chedongATbigfoot.com/chedongATchedong.com
    * $Id: hello_unicode.html,v 1.4 2003/03/09 08:41:47 chedong Exp $
    */

    import java.util.*;
    import java.text.*;

    /**
    * 目的:
    * 顯示環(huán)境變量和JVM的缺省屬性
    * 輸入:無
    * 輸出:
    * 1 支持的LOCALE
    * 2 JVM的缺省屬性
    */

    public class Env {
    /**
    * main entrance
    */
    public static void main(String[] args) {

    System.out.println("Hello, it's: " + new Date());

    //print available locales
    Locale list[] = DateFormat.getAvailableLocales();
    System.out.println("======System available locales:======== ");
    for (int i = 0; i < list.length; i++) {
    System.out.println(list[i].toString() + "\t" + list[i].getDisplayName());
    }

    //print JVM default properties
    System.out.println("======System property======== ");
    System.getProperties().list(System.out);
    }
    }

    最需要注意的是JVM的file.encoding屬性,這個(gè)屬性確定了JVM的缺省的編碼/解碼方式:從而影響應(yīng)用中所有字節(jié)流==>字符流的解碼方式 ,字符流==>字節(jié)流的編碼方式。

        LINUX下的LOCALE可以通過 LANG=zh_CN; LC_ALL=zh_CN.GBK; export LANG LC_ALL 設(shè)置。locale 命令可以顯示系統(tǒng)當(dāng)前的環(huán)境設(shè)置
        Windows的LOCALE可以通過 控制面板==>區(qū)域設(shè)置 設(shè)置實(shí)現(xiàn)

    GNU/Linux 2.4.x (J2SE1.3.1)
    LANG=en_US LC_ALL=en_US
    GNU/Linux 2.4.x (J2SE1.3.1)
    LANG=zh_CN LC_ALL=zh_CN.GBK
    Windows 2000(J2SE1.3.0) 
    區(qū)域設(shè)置:中國(guó)  中文
    Windows 2000(J2SE1.3.0) 
    區(qū)域設(shè)置:英國(guó) 英文
    Hello, it's: Tue Jul 30 11:05:44 CST 2002
    ======System available locales:========
    en English
    en_US English (United States)
    ar Arabic
    ar_AE Arabic (United Arab Emirates)
    ar_BH Arabic (Bahrain)
    ar_DZ Arabic (Algeria)
    ar_EG Arabic (Egypt)
    ar_IQ Arabic (Iraq)
    ar_JO Arabic (Jordan)
    ar_KW Arabic (Kuwait)
    ar_LB Arabic (Lebanon)
    ar_LY Arabic (Libya)
    ar_MA Arabic (Morocco)
    ar_OM Arabic (Oman)
    ar_QA Arabic (Qatar)
    ar_SA Arabic (Saudi Arabia)
    ar_SD Arabic (Sudan)
    ar_SY Arabic (Syria)
    ar_TN Arabic (Tunisia)
    ar_YE Arabic (Yemen)
    be Byelorussian
    be_BY Byelorussian (Belarus)
    bg Bulgarian
    bg_BG Bulgarian (Bulgaria)
    ca Catalan
    ca_ES Catalan (Spain)
    ca_ES_EURO Catalan (Spain,Euro)
    cs Czech
    cs_CZ Czech (Czech Republic)
    da Danish
    da_DK Danish (Denmark)
    de German
    de_AT German (Austria)
    de_AT_EURO German (Austria,Euro)
    de_CH German (Switzerland)
    de_DE German (Germany)
    de_DE_EURO German (Germany,Euro)
    de_LU German (Luxembourg)
    de_LU_EURO German (Luxembourg,Euro)
    el Greek
    el_GR Greek (Greece)
    en_AU English (Australia)
    en_CA English (Canada)
    en_GB English (United Kingdom)
    en_IE English (Ireland)
    en_IE_EURO English (Ireland,Euro)
    en_NZ English (New Zealand)
    en_ZA English (South Africa)
    es Spanish
    es_BO Spanish (Bolivia)
    es_AR Spanish (Argentina)
    es_CL Spanish (Chile)
    es_CO Spanish (Colombia)
    es_CR Spanish (Costa Rica)
    es_DO Spanish (Dominican Republic)
    es_EC Spanish (Ecuador)
    es_ES Spanish (Spain)
    es_ES_EURO Spanish (Spain,Euro)
    es_GT Spanish (Guatemala)
    es_HN Spanish (Honduras)
    es_MX Spanish (Mexico)
    es_NI Spanish (Nicaragua)
    et Estonian
    es_PA Spanish (Panama)
    es_PE Spanish (Peru)
    es_PR Spanish (Puerto Rico)
    es_PY Spanish (Paraguay)
    es_SV Spanish (El Salvador)
    es_UY Spanish (Uruguay)
    es_VE Spanish (Venezuela)
    et_EE Estonian (Estonia)
    fi Finnish
    fi_FI Finnish (Finland)
    fi_FI_EURO Finnish (Finland,Euro)
    fr French
    fr_BE French (Belgium)
    fr_BE_EURO French (Belgium,Euro)
    fr_CA French (Canada)
    fr_CH French (Switzerland)
    fr_FR French (France)
    fr_FR_EURO French (France,Euro)
    fr_LU French (Luxembourg)
    fr_LU_EURO French (Luxembourg,Euro)
    hr Croatian
    hr_HR Croatian (Croatia)
    hu Hungarian
    hu_HU Hungarian (Hungary)
    is Icelandic
    is_IS Icelandic (Iceland)
    it Italian
    it_CH Italian (Switzerland)
    it_IT Italian (Italy)
    it_IT_EURO Italian (Italy,Euro)
    iw Hebrew
    iw_IL Hebrew (Israel)
    ja Japanese
    ja_JP Japanese (Japan)
    ko Korean
    ko_KR Korean (South Korea)
    lt Lithuanian
    lt_LT Lithuanian (Lithuania)
    lv Latvian (Lettish)
    lv_LV Latvian (Lettish) (Latvia)
    mk Macedonian
    mk_MK Macedonian (Macedonia)
    nl Dutch
    nl_BE Dutch (Belgium)
    nl_BE_EURO Dutch (Belgium,Euro)
    nl_NL Dutch (Netherlands)
    nl_NL_EURO Dutch (Netherlands,Euro)
    no Norwegian
    no_NO Norwegian (Norway)
    no_NO_NY Norwegian (Norway,Nynorsk)
    pl Polish
    pl_PL Polish (Poland)
    pt Portuguese
    pt_BR Portuguese (Brazil)
    pt_PT Portuguese (Portugal)
    pt_PT_EURO Portuguese (Portugal,Euro)
    ro Romanian
    ro_RO Romanian (Romania)
    ru Russian
    ru_RU Russian (Russia)
    sh Serbo-Croatian
    sh_YU Serbo-Croatian (Yugoslavia)
    sk Slovak
    sk_SK Slovak (Slovakia)
    sl Slovenian
    sl_SI Slovenian (Slovenia)
    sq Albanian
    sq_AL Albanian (Albania)
    sr Serbian
    sr_YU Serbian (Yugoslavia)
    sv Swedish
    sv_SE Swedish (Sweden)
    th Thai
    th_TH Thai (Thailand)
    tr Turkish
    tr_TR Turkish (Turkey)
    uk Ukrainian
    uk_UA Ukrainian (Ukraine)
    zh Chinese
    zh_CN Chinese (China)
    zh_HK Chinese (Hong Kong)
    zh_TW Chinese (Taiwan)
    ======System property========
    -- listing properties --
    java.runtime.name=Java(TM) 2 Runtime Environment, Stand...
    sun.boot.library.path=/usr/java/jdk1.3.1_04/jre/lib/i386
    java.vm.version=1.3.1_04-b02
    java.vm.vendor=Sun Microsystems Inc.
    java.vendor.url=http://java.sun.com/
    path.separator=:
    java.vm.name=Java HotSpot(TM) Client VM
    file.encoding.pkg=sun.io
    java.vm.specification.name=Java Virtual Machine Specification
    user.dir=/home/chedong/src/char_test
    java.runtime.version=1.3.1_04-b02
    java.awt.graphicsenv=sun.awt.X11GraphicsEnvironment
    os.arch=i386
    java.io.tmpdir=/tmp
    line.separator=

    java.vm.specification.vendor=Sun Microsystems Inc.
    java.awt.fonts=
    os.name=Linux
    java.library.path=/usr/java/jdk1.3.1_04/jre/lib/i386:/u...
    java.specification.name=Java Platform API Specification
    java.class.version=47.0
    os.version=2.4.7-10
    user.home=/home/chedong
    user.timezone=Asia/Shanghai
    java.awt.printerjob=sun.awt.motif.PSPrinterJob
    file.encoding=ISO-8859-1
    java.specification.version=1.3
    user.name=chedong
    java.class.path=/home/chedong/classes
    java.vm.specification.version=1.0
    java.home=/usr/java/jdk1.3.1_04/jre
    user.language=en
    java.specification.vendor=Sun Microsystems Inc.
    java.vm.info=mixed mode
    java.version=1.3.1_04
    java.ext.dirs=/usr/java/jdk1.3.1_04/jre/lib/ext
    sun.boot.class.path=/usr/java/jdk1.3.1_04/jre/lib/rt.jar:...
    java.vendor=Sun Microsystems Inc.
    file.separator=/
    java.vendor.url.bug=http://java.sun.com/cgi-bin/bugreport...
    sun.cpu.endian=little
    sun.io.unicode.encoding=UnicodeLittle
    user.region=US
    sun.cpu.isalist=

    Hello, it's: Tue Jul 30 11:07:34 CST 2002
    ======System available locales:========
    en 英文
    en_US 英文 (美國(guó))
    ar 阿拉伯文
    ar_AE 阿拉伯文 (阿拉伯聯(lián)合酋長(zhǎng)國(guó))
    ar_BH 阿拉伯文 (巴林)
    ar_DZ 阿拉伯文 (阿爾及利亞)
    ar_EG 阿拉伯文 (埃及)
    ar_IQ 阿拉伯文 (伊拉克)
    ar_JO 阿拉伯文 (約旦)
    ar_KW 阿拉伯文 (科威特)
    ar_LB 阿拉伯文 (黎巴嫩)
    ar_LY 阿拉伯文 (利比亞)
    ar_MA 阿拉伯文 (摩洛哥)
    ar_OM 阿拉伯文 (阿曼)
    ar_QA 阿拉伯文 (卡塔爾)
    ar_SA 阿拉伯文 (沙特阿拉伯)
    ar_SD 阿拉伯文 (蘇丹)
    ar_SY 阿拉伯文 (敘利亞)
    ar_TN 阿拉伯文 (突尼斯)
    ar_YE 阿拉伯文 (也門)
    be 白俄羅斯文
    be_BY 白俄羅斯文 (白俄羅斯)
    bg 保加利亞文
    bg_BG 保加利亞文 (保加利亞)
    ca 加泰羅尼亞文
    ca_ES 加泰羅尼亞文 (西班牙)
    ca_ES_EURO 加泰羅尼亞文 (西班牙,Euro)
    cs 捷克文
    cs_CZ 捷克文 (捷克共和國(guó))
    da 丹麥文
    da_DK 丹麥文 (丹麥)
    de 德文
    de_AT 德文 (奧地利)
    de_AT_EURO 德文 (奧地利,Euro)
    de_CH 德文 (瑞士)
    de_DE 德文 (德國(guó))
    de_DE_EURO 德文 (德國(guó),Euro)
    de_LU 德文 (盧森堡)
    de_LU_EURO 德文 (盧森堡,Euro)
    el 希臘文
    el_GR 希臘文 (希臘)
    en_AU 英文 (澳大利亞)
    en_CA 英文 (加拿大)
    en_GB 英文 (英國(guó))
    en_IE 英文 (愛爾蘭)
    en_IE_EURO 英文 (愛爾蘭,Euro)
    en_NZ 英文 (新西蘭)
    en_ZA 英文 (南非)
    es 西班牙文
    es_BO 西班牙文 (玻利維亞)
    es_AR 西班牙文 (阿根廷)
    es_CL 西班牙文 (智利)
    es_CO 西班牙文 (哥倫比亞)
    es_CR 西班牙文 (哥斯達(dá)黎加)
    es_DO 西班牙文 (多米尼加共和國(guó))
    es_EC 西班牙文 (厄瓜多爾)
    es_ES 西班牙文 (西班牙)
    es_ES_EURO 西班牙文 (西班牙,Euro)
    es_GT 西班牙文 (危地馬拉)
    es_HN 西班牙文 (洪都拉斯)
    es_MX 西班牙文 (墨西哥)
    es_NI 西班牙文 (尼加拉瓜)
    et 愛沙尼亞文
    es_PA 西班牙文 (巴拿馬)
    es_PE 西班牙文 (秘魯)
    es_PR 西班牙文 (波多黎哥)
    es_PY 西班牙文 (巴拉圭)
    es_SV 西班牙文 (薩爾瓦多)
    es_UY 西班牙文 (烏拉圭)
    es_VE 西班牙文 (委內(nèi)瑞拉)
    et_EE 愛沙尼亞文 (愛沙尼亞)
    fi 芬蘭文
    fi_FI 芬蘭文 (芬蘭)
    fi_FI_EURO 芬蘭文 (芬蘭,Euro)
    fr 法文
    fr_BE 法文 (比利時(shí))
    fr_BE_EURO 法文 (比利時(shí),Euro)
    fr_CA 法文 (加拿大)
    fr_CH 法文 (瑞士)
    fr_FR 法文 (法國(guó))
    fr_FR_EURO 法文 (法國(guó),Euro)
    fr_LU 法文 (盧森堡)
    fr_LU_EURO 法文 (盧森堡,Euro)
    hr 克羅地亞文
    hr_HR 克羅地亞文 (克羅地亞)
    hu 匈牙利文
    hu_HU 匈牙利文 (匈牙利)
    is 冰島文
    is_IS 冰島文 (冰島)
    it 意大利文
    it_CH 意大利文 (瑞士)
    it_IT 意大利文 (意大利)
    it_IT_EURO 意大利文 (意大利,Euro)
    iw 希伯來文
    iw_IL 希伯來文 (以色列)
    ja 日文
    ja_JP 日文 (日本)
    ko 朝鮮文
    ko_KR 朝鮮文 (南朝鮮)
    lt 立陶宛文
    lt_LT 立陶宛文 (立陶宛)
    lv 拉托維亞文(列托)
    lv_LV 拉托維亞文(列托) (拉脫維亞)
    mk 馬其頓文
    mk_MK 馬其頓文 (馬其頓王國(guó))
    nl 荷蘭文
    nl_BE 荷蘭文 (比利時(shí))
    nl_BE_EURO 荷蘭文 (比利時(shí),Euro)
    nl_NL 荷蘭文 (荷蘭)
    nl_NL_EURO 荷蘭文 (荷蘭,Euro)
    no 挪威文
    no_NO 挪威文 (挪威)
    no_NO_NY 挪威文 (挪威,Nynorsk)
    pl 波蘭文
    pl_PL 波蘭文 (波蘭)
    pt 葡萄牙文
    pt_BR 葡萄牙文 (巴西)
    pt_PT 葡萄牙文 (葡萄牙)
    pt_PT_EURO 葡萄牙文 (葡萄牙,Euro)
    ro 羅馬尼亞文
    ro_RO 羅馬尼亞文 (羅馬尼亞)
    ru 俄文
    ru_RU 俄文 (俄羅斯)
    sh 塞波尼斯-克羅地亞文
    sh_YU 塞波尼斯-克羅地亞文 (南斯拉夫)
    sk 斯洛伐克文
    sk_SK 斯洛伐克文 (斯洛伐克)
    sl 斯洛文尼亞文
    sl_SI 斯洛文尼亞文 (斯洛文尼亞)
    sq 阿爾巴尼亞文
    sq_AL 阿爾巴尼亞文 (阿爾巴尼亞)
    sr 塞爾維亞文
    sr_YU 塞爾維亞文 (南斯拉夫)
    sv 瑞典文
    sv_SE 瑞典文 (瑞典)
    th 泰文
    th_TH 泰文 (泰國(guó))
    tr 土耳其文
    tr_TR 土耳其文 (土耳其)
    uk 烏克蘭文
    uk_UA 烏克蘭文 (烏克蘭)
    zh 中文
    zh_CN 中文 (中國(guó))
    zh_HK 中文 (香港)
    zh_TW 中文 (臺(tái)灣)
    ======System property========
    -- listing properties --
    java.runtime.name=Java(TM) 2 Runtime Environment, Stand...
    sun.boot.library.path=/usr/java/jdk1.3.1_04/jre/lib/i386
    java.vm.version=1.3.1_04-b02
    java.vm.vendor=Sun Microsystems Inc.
    java.vendor.url=http://java.sun.com/
    path.separator=:
    java.vm.name=Java HotSpot(TM) Client VM
    file.encoding.pkg=sun.io
    java.vm.specification.name=Java Virtual Machine Specification
    user.dir=/home/chedong/src/char_test
    java.runtime.version=1.3.1_04-b02
    java.awt.graphicsenv=sun.awt.X11GraphicsEnvironment
    os.arch=i386
    java.io.tmpdir=/tmp
    line.separator=

    java.vm.specification.vendor=Sun Microsystems Inc.
    java.awt.fonts=
    os.name=Linux
    java.library.path=/usr/java/jdk1.3.1_04/jre/lib/i386:/u...
    java.specification.name=Java Platform API Specification
    java.class.version=47.0
    os.version=2.4.7-10
    user.home=/home/chedong
    user.timezone=Asia/Shanghai
    java.awt.printerjob=sun.awt.motif.PSPrinterJob
    file.encoding=GBK
    java.specification.version=1.3
    user.name=chedong
    java.class.path=/home/chedong/classes
    java.vm.specification.version=1.0
    java.home=/usr/java/jdk1.3.1_04/jre
    user.language=zh
    java.specification.vendor=Sun Microsystems Inc.
    java.vm.info=mixed mode
    java.version=1.3.1_04
    java.ext.dirs=/usr/java/jdk1.3.1_04/jre/lib/ext
    sun.boot.class.path=/usr/java/jdk1.3.1_04/jre/lib/rt.jar:...
    java.vendor=Sun Microsystems Inc.
    file.separator=/
    java.vendor.url.bug=http://java.sun.com/cgi-bin/bugreport...
    sun.cpu.endian=little
    sun.io.unicode.encoding=UnicodeLittle
    user.region=CN
    sun.cpu.isalist=
    Hello, it's: Tue Jul 30 11:49:36 CST 2002
    ======System available locales:========
    en English
    en_US English (United States)
    ar Arabic
    ar_AE Arabic (United Arab Emirates)
    ar_BH Arabic (Bahrain)
    ar_DZ Arabic (Algeria)
    ar_EG Arabic (Egypt)
    ar_IQ Arabic (Iraq)
    ar_JO Arabic (Jordan)
    ar_KW Arabic (Kuwait)
    ar_LB Arabic (Lebanon)
    ar_LY Arabic (Libya)
    ar_MA Arabic (Morocco)
    ar_OM Arabic (Oman)
    ar_QA Arabic (Qatar)
    ar_SA Arabic (Saudi Arabia)
    ar_SD Arabic (Sudan)
    ar_SY Arabic (Syria)
    ar_TN Arabic (Tunisia)
    ar_YE Arabic (Yemen)
    be Byelorussian
    be_BY Byelorussian (Belarus)
    bg Bulgarian
    bg_BG Bulgarian (Bulgaria)
    ca Catalan
    ca_ES Catalan (Spain)
    ca_ES_EURO Catalan (Spain,Euro)
    cs Czech
    cs_CZ Czech (Czech Republic)
    da Danish
    da_DK Danish (Denmark)
    de German
    de_AT German (Austria)
    de_AT_EURO German (Austria,Euro)
    de_CH German (Switzerland)
    de_DE German (Germany)
    de_DE_EURO German (Germany,Euro)
    de_LU German (Luxembourg)
    de_LU_EURO German (Luxembourg,Euro)
    el Greek
    el_GR Greek (Greece)
    en_AU English (Australia)
    en_CA English (Canada)
    en_GB English (United Kingdom)
    en_IE English (Ireland)
    en_IE_EURO English (Ireland,Euro)
    en_NZ English (New Zealand)
    en_ZA English (South Africa)
    es Spanish
    es_AR Spanish (Argentina)
    es_BO Spanish (Bolivia)
    es_CL Spanish (Chile)
    es_CO Spanish (Colombia)
    es_CR Spanish (Costa Rica)
    es_DO Spanish (Dominican Republic)
    es_EC Spanish (Ecuador)
    es_ES Spanish (Spain)
    es_ES_EURO Spanish (Spain,Euro)
    es_GT Spanish (Guatemala)
    es_HN Spanish (Honduras)
    es_MX Spanish (Mexico)
    es_NI Spanish (Nicaragua)
    es_PA Spanish (Panama)
    es_PE Spanish (Peru)
    es_PR Spanish (Puerto Rico)
    es_PY Spanish (Paraguay)
    es_SV Spanish (El Salvador)
    es_UY Spanish (Uruguay)
    es_VE Spanish (Venezuela)
    et Estonian
    et_EE Estonian (Estonia)
    fi Finnish
    fi_FI Finnish (Finland)
    fi_FI_EURO Finnish (Finland,Euro)
    fr French
    fr_BE French (Belgium)
    fr_BE_EURO French (Belgium,Euro)
    fr_CA French (Canada)
    fr_CH French (Switzerland)
    fr_FR French (France)
    fr_FR_EURO French (France,Euro)
    fr_LU French (Luxembourg)
    fr_LU_EURO French (Luxembourg,Euro)
    hr Croatian
    hr_HR Croatian (Croatia)
    hu Hungarian
    hu_HU Hungarian (Hungary)
    is Icelandic
    is_IS Icelandic (Iceland)
    it Italian
    it_CH Italian (Switzerland)
    it_IT Italian (Italy)
    it_IT_EURO Italian (Italy,Euro)
    iw Hebrew
    iw_IL Hebrew (Israel)
    ja Japanese
    ja_JP Japanese (Japan)
    ko 韓文
    ko_KR 韓文 (大韓民國(guó))
    lt Lithuanian
    lt_LT Lithuanian (Lithuania)
    lv Latvian (Lettish)
    lv_LV Latvian (Lettish) (Latvia)
    mk Macedonian
    mk_MK Macedonian (Macedonia)
    nl Dutch
    nl_BE Dutch (Belgium)
    nl_BE_EURO Dutch (Belgium,Euro)
    nl_NL Dutch (Netherlands)
    nl_NL_EURO Dutch (Netherlands,Euro)
    no Norwegian
    no_NO Norwegian (Norway)
    no_NO_NY Norwegian (Norway,Nynorsk)
    pl Polish
    pl_PL Polish (Poland)
    pt Portuguese
    pt_BR Portuguese (Brazil)
    pt_PT Portuguese (Portugal)
    pt_PT_EURO Portuguese (Portugal,Euro)
    ro Romanian
    ro_RO Romanian (Romania)
    ru Russian
    ru_RU Russian (Russia)
    sh Serbo-Croatian
    sh_YU Serbo-Croatian (Yugoslavia)
    sk Slovak
    sk_SK Slovak (Slovakia)
    sl Slovenian
    sl_SI Slovenian (Slovenia)
    sq Albanian
    sq_AL Albanian (Albania)
    sr Serbian
    sr_YU Serbian (Yugoslavia)
    sv Swedish
    sv_SE Swedish (Sweden)
    th Thai
    th_TH Thai (Thailand)
    tr Turkish
    tr_TR Turkish (Turkey)
    uk Ukrainian
    uk_UA Ukrainian (Ukraine)
    zh 中文
    zh_CN 中文 (中華人民共和國(guó))
    zh_HK 中文 (香港)
    zh_TW 中文 (臺(tái)灣)
    ======System property========
    -- listing properties --
    java.runtime.name=Java(TM) 2 Runtime Environment, Stand...
    sun.boot.library.path=C:\PROGRAM FILES\JavaSOFT\JRE\1.3.0_0...
    java.vm.version=1.3.0_02
    java.vm.vendor=Sun Microsystems Inc.
    java.vendor.url=http://java.sun.com/
    path.separator=;
    java.vm.name=Java HotSpot(TM) Client VM
    file.encoding.pkg=sun.io
    java.vm.specification.name=Java Virtual Machine Specification
    user.dir=D:\java\src\char_test
    java.runtime.version=1.3.0_02
    java.awt.graphicsenv=sun.awt.Win32GraphicsEnvironment
    os.arch=x86
    java.io.tmpdir=D:\TEMP\
    line.separator=

    java.vm.specification.vendor=Sun Microsystems Inc.
    java.awt.fonts=
    os.name=Windows 98
    java.library.path=C:\WINDOWS;.;C:\WINDOWS\SYSTEM;C:\WIN...
    java.specification.name=Java Platform API Specification
    java.class.version=47.0
    os.version=4.90
    user.home=C:\WINDOWS
    user.timezone=Asia/Shanghai
    java.awt.printerjob=sun.awt.windows.WPrinterJob
    file.encoding=GBK
    java.specification.version=1.3
    user.name=Sicci
    java.class.path=d:\java\classes
    java.vm.specification.version=1.0
    java.home=C:\PROGRAM FILES\JavaSOFT\JRE\1.3.0_02
    user.language=zh
    java.specification.vendor=Sun Microsystems Inc.
    awt.toolkit=sun.awt.windows.WToolkit
    java.vm.info=mixed mode
    java.version=1.3.0_02
    java.ext.dirs=C:\PROGRAM FILES\JavaSOFT\JRE\1.3.0_0...
    sun.boot.class.path=C:\PROGRAM FILES\JavaSOFT\JRE\1.3.0_0...
    java.vendor=Sun Microsystems Inc.
    file.separator=\
    java.vendor.url.bug=http://java.sun.com/cgi-bin/bugreport...
    sun.cpu.endian=little
    sun.io.unicode.encoding=UnicodeLittle
    user.region=CN
    sun.cpu.isalist=pentium i486 i386
    Hello, it's: Tue Jul 30 11:53:27 CST 2002
    ======System available locales:========
    en English
    en_US English (United States)
    ar Arabic
    ar_AE Arabic (United Arab Emirates)
    ar_BH Arabic (Bahrain)
    ar_DZ Arabic (Algeria)
    ar_EG Arabic (Egypt)
    ar_IQ Arabic (Iraq)
    ar_JO Arabic (Jordan)
    ar_KW Arabic (Kuwait)
    ar_LB Arabic (Lebanon)
    ar_LY Arabic (Libya)
    ar_MA Arabic (Morocco)
    ar_OM Arabic (Oman)
    ar_QA Arabic (Qatar)
    ar_SA Arabic (Saudi Arabia)
    ar_SD Arabic (Sudan)
    ar_SY Arabic (Syria)
    ar_TN Arabic (Tunisia)
    ar_YE Arabic (Yemen)
    be Byelorussian
    be_BY Byelorussian (Belarus)
    bg Bulgarian
    bg_BG Bulgarian (Bulgaria)
    ca Catalan
    ca_ES Catalan (Spain)
    ca_ES_EURO Catalan (Spain,Euro)
    cs Czech
    cs_CZ Czech (Czech Republic)
    da Danish
    da_DK Danish (Denmark)
    de German
    de_AT German (Austria)
    de_AT_EURO German (Austria,Euro)
    de_CH German (Switzerland)
    de_DE German (Germany)
    de_DE_EURO German (Germany,Euro)
    de_LU German (Luxembourg)
    de_LU_EURO German (Luxembourg,Euro)
    el Greek
    el_GR Greek (Greece)
    en_AU English (Australia)
    en_CA English (Canada)
    en_GB English (United Kingdom)
    en_IE English (Ireland)
    en_IE_EURO English (Ireland,Euro)
    en_NZ English (New Zealand)
    en_ZA English (South Africa)
    es Spanish
    es_AR Spanish (Argentina)
    es_BO Spanish (Bolivia)
    es_CL Spanish (Chile)
    es_CO Spanish (Colombia)
    es_CR Spanish (Costa Rica)
    es_DO Spanish (Dominican Republic)
    es_EC Spanish (Ecuador)
    es_ES Spanish (Spain)
    es_ES_EURO Spanish (Spain,Euro)
    es_GT Spanish (Guatemala)
    es_HN Spanish (Honduras)
    es_MX Spanish (Mexico)
    es_NI Spanish (Nicaragua)
    es_PA Spanish (Panama)
    es_PE Spanish (Peru)
    es_PR Spanish (Puerto Rico)
    es_PY Spanish (Paraguay)
    es_SV Spanish (El Salvador)
    es_UY Spanish (Uruguay)
    es_VE Spanish (Venezuela)
    et Estonian
    et_EE Estonian (Estonia)
    fi Finnish
    fi_FI Finnish (Finland)
    fi_FI_EURO Finnish (Finland,Euro)
    fr French
    fr_BE French (Belgium)
    fr_BE_EURO French (Belgium,Euro)
    fr_CA French (Canada)
    fr_CH French (Switzerland)
    fr_FR French (France)
    fr_FR_EURO French (France,Euro)
    fr_LU French (Luxembourg)
    fr_LU_EURO French (Luxembourg,Euro)
    hr Croatian
    hr_HR Croatian (Croatia)
    hu Hungarian
    hu_HU Hungarian (Hungary)
    is Icelandic
    is_IS Icelandic (Iceland)
    it Italian
    it_CH Italian (Switzerland)
    it_IT Italian (Italy)
    it_IT_EURO Italian (Italy,Euro)
    iw Hebrew
    iw_IL Hebrew (Israel)
    ja Japanese
    ja_JP Japanese (Japan)
    ko Korean
    ko_KR Korean (South Korea)
    lt Lithuanian
    lt_LT Lithuanian (Lithuania)
    lv Latvian (Lettish)
    lv_LV Latvian (Lettish) (Latvia)
    mk Macedonian
    mk_MK Macedonian (Macedonia)
    nl Dutch
    nl_BE Dutch (Belgium)
    nl_BE_EURO Dutch (Belgium,Euro)
    nl_NL Dutch (Netherlands)
    nl_NL_EURO Dutch (Netherlands,Euro)
    no Norwegian
    no_NO Norwegian (Norway)
    no_NO_NY Norwegian (Norway,Nynorsk)
    pl Polish
    pl_PL Polish (Poland)
    pt Portuguese
    pt_BR Portuguese (Brazil)
    pt_PT Portuguese (Portugal)
    pt_PT_EURO Portuguese (Portugal,Euro)
    ro Romanian
    ro_RO Romanian (Romania)
    ru Russian
    ru_RU Russian (Russia)
    sh Serbo-Croatian
    sh_YU Serbo-Croatian (Yugoslavia)
    sk Slovak
    sk_SK Slovak (Slovakia)
    sl Slovenian
    sl_SI Slovenian (Slovenia)
    sq Albanian
    sq_AL Albanian (Albania)
    sr Serbian
    sr_YU Serbian (Yugoslavia)
    sv Swedish
    sv_SE Swedish (Sweden)
    th Thai
    th_TH Thai (Thailand)
    tr Turkish
    tr_TR Turkish (Turkey)
    uk Ukrainian
    uk_UA Ukrainian (Ukraine)
    zh Chinese
    zh_CN Chinese (China)
    zh_HK Chinese (Hong Kong)
    zh_TW Chinese (Taiwan)
    ======System property========
    -- listing properties --
    java.runtime.name=Java(TM) 2 Runtime Environment, Stand...
    sun.boot.library.path=C:\PROGRAM FILES\JavaSOFT\JRE\1.3.0_0...
    java.vm.version=1.3.0_02
    java.vm.vendor=Sun Microsystems Inc.
    java.vendor.url=http://java.sun.com/
    path.separator=;
    java.vm.name=Java HotSpot(TM) Client VM
    file.encoding.pkg=sun.io
    java.vm.specification.name=Java Virtual Machine Specification
    user.dir=D:\java\src\char_test
    java.runtime.version=1.3.0_02
    java.awt.graphicsenv=sun.awt.Win32GraphicsEnvironment
    os.arch=x86
    java.io.tmpdir=D:\TEMP\
    line.separator=

    java.vm.specification.vendor=Sun Microsystems Inc.
    java.awt.fonts=
    os.name=Windows 98
    java.library.path=C:\WINDOWS;.;C:\WINDOWS\SYSTEM;C:\WIN...
    java.specification.name=Java Platform API Specification
    java.class.version=47.0
    os.version=4.90
    user.home=C:\WINDOWS
    user.timezone=Asia/Shanghai
    java.awt.printerjob=sun.awt.windows.WPrinterJob
    file.encoding=Cp1252
    java.specification.version=1.3
    user.name=Sicci
    java.class.path=d:\java\classes
    java.vm.specification.version=1.0
    java.home=C:\PROGRAM FILES\JavaSOFT\JRE\1.3.0_02
    user.language=en
    java.specification.vendor=Sun Microsystems Inc.
    awt.toolkit=sun.awt.windows.WToolkit
    java.vm.info=mixed mode
    java.version=1.3.0_02
    java.ext.dirs=C:\PROGRAM FILES\JavaSOFT\JRE\1.3.0_0...
    sun.boot.class.path=C:\PROGRAM FILES\JavaSOFT\JRE\1.3.0_0...
    java.vendor=Sun Microsystems Inc.
    file.separator=\
    java.vendor.url.bug=http://java.sun.com/cgi-bin/bugreport...
    sun.cpu.endian=little
    sun.io.unicode.encoding=UnicodeLittle
    user.region=GB
    sun.cpu.isalist=pentium i486 i386

    結(jié)論1:

    JVM的缺省編碼方式由系統(tǒng)的“本地語(yǔ)言環(huán)境”設(shè)置確定,和操作系統(tǒng)的類型無關(guān)所以當(dāng)設(shè)置成相同的LOCALE 時(shí),Linux和Windows下的缺省編碼方式是沒有區(qū)別的(可以認(rèn)為cp1252=ISO-8859-1都是一樣的西文編碼方式,只包含255以下的 拉丁字符),因此后面的測(cè)試2我只列出了GNU/Linux下LOCALE分別設(shè)置成zh_CN和en_US的測(cè)試結(jié)果輸出。以下測(cè)試如果在 Windows下分別按照不同的區(qū)域和字符集設(shè)置后試驗(yàn)的輸出是一樣的。

    試驗(yàn)2:Java的輸入輸出過程中的字節(jié)流到字符流的轉(zhuǎn)換過程

    通過這個(gè)HelloUnicode.java程序,演示說明"Hello world 世界你好"這個(gè)字符串(16個(gè)字符)在不同缺省系統(tǒng)編碼方式下的處理效果。在編碼/解碼的每個(gè)步驟之后,都打印出了相應(yīng)字符串每個(gè)字符(Charactor)的byte值,short值和所在的UNICODE區(qū)間。

    LANG=en_US LC_ALL=en_US LANG=zh_CN LC_ALL=zh_CN.GBK
    ========testing1: write hello world to files========
    [test 1-1]: with system default encoding=ISO-8859-1
    string=Hello world 世界你好 length=20
    char[0]='H' byte=72 \u48 short=72 \u48 BASIC_LATIN
    char[1]='e' byte=101 \u65 short=101 \u65 BASIC_LATIN
    char[2]='l' byte=108 \u6C short=108 \u6C BASIC_LATIN
    char[3]='l' byte=108 \u6C short=108 \u6C BASIC_LATIN
    char[4]='o' byte=111 \u6F short=111 \u6F BASIC_LATIN
    char[5]=' ' byte=32 \u20 short=32 \u20 BASIC_LATIN
    char[6]='w' byte=119 \u77 short=119 \u77 BASIC_LATIN
    char[7]='o' byte=111 \u6F short=111 \u6F BASIC_LATIN
    char[8]='r' byte=114 \u72 short=114 \u72 BASIC_LATIN
    char[9]='l' byte=108 \u6C short=108 \u6C BASIC_LATIN
    char[10]='d' byte=100 \u64 short=100 \u64 BASIC_LATIN
    char[11]=' ' byte=32 \u20 short=32 \u20 BASIC_LATIN
    char[12]='? byte=-54 \uFFFFFFCA short=202 \uCA LATIN_1_SUPPLEMENT
    char[13]='? byte=-64 \uFFFFFFC0 short=192 \uC0 LATIN_1_SUPPLEMENT
    char[14]='? byte=-67 \uFFFFFFBD short=189 \uBD LATIN_1_SUPPLEMENT
    char[15]='? byte=-25 \uFFFFFFE7 short=231 \uE7 LATIN_1_SUPPLEMENT
    char[16]='? byte=-60 \uFFFFFFC4 short=196 \uC4 LATIN_1_SUPPLEMENT
    char[17]='? byte=-29 \uFFFFFFE3 short=227 \uE3 LATIN_1_SUPPLEMENT
    char[18]='? byte=-70 \uFFFFFFBA short=186 \uBA LATIN_1_SUPPLEMENT
    char[19]='? byte=-61 \uFFFFFFC3 short=195 \uC3 LATIN_1_SUPPLEMENT

    第1步:在英文編碼環(huán)境下,雖然屏幕上正確的顯示了中文,
    但實(shí)際上它打印的是“半個(gè)”漢字,將結(jié)果寫入第1個(gè)文件 hello.orig.html


    [test 1-2]: getBytes with platform default encoding and decoding as gb2312:
    string=Hello world ???? length=16
    char[0]='H' byte=72 \u48 short=72 \u48 BASIC_LATIN
    char[1]='e' byte=101 \u65 short=101 \u65 BASIC_LATIN
    char[2]='l' byte=108 \u6C short=108 \u6C BASIC_LATIN
    char[3]='l' byte=108 \u6C short=108 \u6C BASIC_LATIN
    char[4]='o' byte=111 \u6F short=111 \u6F BASIC_LATIN
    char[5]=' ' byte=32 \u20 short=32 \u20 BASIC_LATIN
    char[6]='w' byte=119 \u77 short=119 \u77 BASIC_LATIN
    char[7]='o' byte=111 \u6F short=111 \u6F BASIC_LATIN
    char[8]='r' byte=114 \u72 short=114 \u72 BASIC_LATIN
    char[9]='l' byte=108 \u6C short=108 \u6C BASIC_LATIN
    char[10]='d' byte=100 \u64 short=100 \u64 BASIC_LATIN
    char[11]=' ' byte=32 \u20 short=32 \u20 BASIC_LATIN
    char[12]='?' byte=22 \u16 short=19990 \u4E16 CJK_UNIFIED_IDEOGRAPHS
    char[13]='?' byte=76 \u4C short=30028 \u754C CJK_UNIFIED_IDEOGRAPHS
    char[14]='?' byte=96 \u60 short=20320 \u4F60 CJK_UNIFIED_IDEOGRAPHS
    char[15]='?' byte=125 \u7D short=22909 \u597D CJK_UNIFIED_IDEOGRAPHS

    按系統(tǒng)缺省編碼重新變成字節(jié)流,然后按照GB2312方式解碼,這里雖然打印出的是問號(hào)
    (因?yàn)楫?dāng)前的英文環(huán)境下系統(tǒng)對(duì)于255以上的字符是不知道用什么字符表示的,因此全部用?顯示)
    但從相應(yīng)的UNICODE MAPPING和SHORT值我們可以知道字符是正確的中文

    但下一步的寫入第2個(gè)文件html.gb2312.html,
    沒有指定編碼方式(按系統(tǒng)缺省的ISO-8859-1編碼方式),
    因此從后面的測(cè)試2-2讀取的結(jié)果是真的'?'了

    [test 1-3]: convert string to UTF8
    string=Hello world 涓栫晫浣犲ソ length=24
    char[0]='H' byte=72 \u48 short=72 \u48 BASIC_LATIN
    char[1]='e' byte=101 \u65 short=101 \u65 BASIC_LATIN
    char[2]='l' byte=108 \u6C short=108 \u6C BASIC_LATIN
    char[3]='l' byte=108 \u6C short=108 \u6C BASIC_LATIN
    char[4]='o' byte=111 \u6F short=111 \u6F BASIC_LATIN
    char[5]=' ' byte=32 \u20 short=32 \u20 BASIC_LATIN
    char[6]='w' byte=119 \u77 short=119 \u77 BASIC_LATIN
    char[7]='o' byte=111 \u6F short=111 \u6F BASIC_LATIN
    char[8]='r' byte=114 \u72 short=114 \u72 BASIC_LATIN
    char[9]='l' byte=108 \u6C short=108 \u6C BASIC_LATIN
    char[10]='d' byte=100 \u64 short=100 \u64 BASIC_LATIN
    char[11]=' ' byte=32 \u20 short=32 \u20 BASIC_LATIN
    char[12]='? byte=-28 \uFFFFFFE4 short=228 \uE4 LATIN_1_SUPPLEMENT
    char[13]='? byte=-72 \uFFFFFFB8 short=184 \uB8 LATIN_1_SUPPLEMENT
    char[14]='? byte=-106 \uFFFFFF96 short=150 \u96 LATIN_1_SUPPLEMENT
    char[15]='? byte=-25 \uFFFFFFE7 short=231 \uE7 LATIN_1_SUPPLEMENT
    char[16]='? byte=-107 \uFFFFFF95 short=149 \u95 LATIN_1_SUPPLEMENT
    char[17]='? byte=-116 \uFFFFFF8C short=140 \u8C LATIN_1_SUPPLEMENT
    char[18]='? byte=-28 \uFFFFFFE4 short=228 \uE4 LATIN_1_SUPPLEMENT
    char[19]='? byte=-67 \uFFFFFFBD short=189 \uBD LATIN_1_SUPPLEMENT
    char[20]='? byte=-96 \uFFFFFFA0 short=160 \uA0 LATIN_1_SUPPLEMENT
    char[21]='? byte=-27 \uFFFFFFE5 short=229 \uE5 LATIN_1_SUPPLEMENT
    char[22]='? byte=-91 \uFFFFFFA5 short=165 \uA5 LATIN_1_SUPPLEMENT
    char[23]='? byte=-67 \uFFFFFFBD short=189 \uBD LATIN_1_SUPPLEMENT

    第3個(gè)試驗(yàn),將字符流按照UTF8方式編碼后,寫入第3個(gè)測(cè)試文件hello.utf8.html,
    我們可以看到UTF8對(duì)英文沒有影響,但對(duì)于其他文字使用了3字節(jié)編碼方式,
    因此比GB2312編碼方式的存儲(chǔ)要大50%,


    ========Testing2: reading and decoding from files========
    [test 2-1]: read hello.orig.html: decoding with system default encoding
    string=Hello world 世界你好 length=20
    char[0]='H' byte=72 \u48 short=72 \u48 BASIC_LATIN
    char[1]='e' byte=101 \u65 short=101 \u65 BASIC_LATIN
    char[2]='l' byte=108 \u6C short=108 \u6C BASIC_LATIN
    char[3]='l' byte=108 \u6C short=108 \u6C BASIC_LATIN
    char[4]='o' byte=111 \u6F short=111 \u6F BASIC_LATIN
    char[5]=' ' byte=32 \u20 short=32 \u20 BASIC_LATIN
    char[6]='w' byte=119 \u77 short=119 \u77 BASIC_LATIN
    char[7]='o' byte=111 \u6F short=111 \u6F BASIC_LATIN
    char[8]='r' byte=114 \u72 short=114 \u72 BASIC_LATIN
    char[9]='l' byte=108 \u6C short=108 \u6C BASIC_LATIN
    char[10]='d' byte=100 \u64 short=100 \u64 BASIC_LATIN
    char[11]=' ' byte=32 \u20 short=32 \u20 BASIC_LATIN
    char[12]='? byte=-54 \uFFFFFFCA short=202 \uCA LATIN_1_SUPPLEMENT
    char[13]='? byte=-64 \uFFFFFFC0 short=192 \uC0 LATIN_1_SUPPLEMENT
    char[14]='? byte=-67 \uFFFFFFBD short=189 \uBD LATIN_1_SUPPLEMENT
    char[15]='? byte=-25 \uFFFFFFE7 short=231 \uE7 LATIN_1_SUPPLEMENT
    char[16]='? byte=-60 \uFFFFFFC4 short=196 \uC4 LATIN_1_SUPPLEMENT
    char[17]='? byte=-29 \uFFFFFFE3 short=227 \uE3 LATIN_1_SUPPLEMENT
    char[18]='? byte=-70 \uFFFFFFBA short=186 \uBA LATIN_1_SUPPLEMENT
    char[19]='? byte=-61 \uFFFFFFC3 short=195 \uC3 LATIN_1_SUPPLEMENT

    按系統(tǒng)從中間存儲(chǔ)hello.orig.html文件中讀取相應(yīng)文件,
    雖然是按字節(jié)方式(半個(gè)“字”)讀取的,但由于能完整的還原,因此輸出顯示沒有錯(cuò)誤。
    其實(shí)PHP等應(yīng)用很少出現(xiàn)字符集問題其實(shí)就是這個(gè)原因,全程都是按字節(jié)流方式處理,
    很好的還原了輸入,但這樣處理的同時(shí)也失去了對(duì)字符的控制


    [test 2-2]: read hello.gb2312.html: decoding as GB2312
    string=Hello world ???? length=16
    char[0]='H' byte=72 \u48 short=72 \u48 BASIC_LATIN
    char[1]='e' byte=101 \u65 short=101 \u65 BASIC_LATIN
    char[2]='l' byte=108 \u6C short=108 \u6C BASIC_LATIN
    char[3]='l' byte=108 \u6C short=108 \u6C BASIC_LATIN
    char[4]='o' byte=111 \u6F short=111 \u6F BASIC_LATIN
    char[5]=' ' byte=32 \u20 short=32 \u20 BASIC_LATIN
    char[6]='w' byte=119 \u77 short=119 \u77 BASIC_LATIN
    char[7]='o' byte=111 \u6F short=111 \u6F BASIC_LATIN
    char[8]='r' byte=114 \u72 short=114 \u72 BASIC_LATIN
    char[9]='l' byte=108 \u6C short=108 \u6C BASIC_LATIN
    char[10]='d' byte=100 \u64 short=100 \u64 BASIC_LATIN
    char[11]=' ' byte=32 \u20 short=32 \u20 BASIC_LATIN
    char[12]='?' byte=63 \u3F short=63 \u3F BASIC_LATIN
    char[13]='?' byte=63 \u3F short=63 \u3F BASIC_LATIN
    char[14]='?' byte=63 \u3F short=63 \u3F BASIC_LATIN
    char[15]='?' byte=63 \u3F short=63 \u3F BASIC_LATIN

    最慘的就是輸出的時(shí)候這些'?'真的是問號(hào)char(63)了,
    數(shù)據(jù)如果是這樣就真的沒救了


    [test 2-3]: read hello.utf8.html: decoding as UTF8
    string=Hello world ???? length=16
    char[0]='H' byte=72 \u48 short=72 \u48 BASIC_LATIN
    char[1]='e' byte=101 \u65 short=101 \u65 BASIC_LATIN
    char[2]='l' byte=108 \u6C short=108 \u6C BASIC_LATIN
    char[3]='l' byte=108 \u6C short=108 \u6C BASIC_LATIN
    char[4]='o' byte=111 \u6F short=111 \u6F BASIC_LATIN
    char[5]=' ' byte=32 \u20 short=32 \u20 BASIC_LATIN
    char[6]='w' byte=119 \u77 short=119 \u77 BASIC_LATIN
    char[7]='o' byte=111 \u6F short=111 \u6F BASIC_LATIN
    char[8]='r' byte=114 \u72 short=114 \u72 BASIC_LATIN
    char[9]='l' byte=108 \u6C short=108 \u6C BASIC_LATIN
    char[10]='d' byte=100 \u64 short=100 \u64 BASIC_LATIN
    char[11]=' ' byte=32 \u20 short=32 \u20 BASIC_LATIN
    char[12]='?' byte=22 \u16 short=19990 \u4E16 CJK_UNIFIED_IDEOGRAPHS
    char[13]='?' byte=76 \u4C short=30028 \u754C CJK_UNIFIED_IDEOGRAPHS
    char[14]='?' byte=96 \u60 short=20320 \u4F60 CJK_UNIFIED_IDEOGRAPHS
    char[15]='?' byte=125 \u7D short=22909 \u597D CJK_UNIFIED_IDEOGRAPHS

    great! 字符雖然顯示為'?',但實(shí)際上字符的解碼是正確的,
    從相應(yīng)的UNICODE MAPPING就可以看的出來。
        ========Testing1: write hello world to files========
    [test 1-1]: with system default encoding=GBK
    string=Hello world 世界你好 length=16
    char[0]='H' byte=72 \u48 short=72 \u48 BASIC_LATIN
    char[1]='e' byte=101 \u65 short=101 \u65 BASIC_LATIN
    char[2]='l' byte=108 \u6C short=108 \u6C BASIC_LATIN
    char[3]='l' byte=108 \u6C short=108 \u6C BASIC_LATIN
    char[4]='o' byte=111 \u6F short=111 \u6F BASIC_LATIN
    char[5]=' ' byte=32 \u20 short=32 \u20 BASIC_LATIN
    char[6]='w' byte=119 \u77 short=119 \u77 BASIC_LATIN
    char[7]='o' byte=111 \u6F short=111 \u6F BASIC_LATIN
    char[8]='r' byte=114 \u72 short=114 \u72 BASIC_LATIN
    char[9]='l' byte=108 \u6C short=108 \u6C BASIC_LATIN
    char[10]='d' byte=100 \u64 short=100 \u64 BASIC_LATIN
    char[11]=' ' byte=32 \u20 short=32 \u20 BASIC_LATIN
    char[12]='世' byte=22 \u16 short=19990 \u4E16 CJK_UNIFIED_IDEOGRAPHS
    char[13]='界' byte=76 \u4C short=30028 \u754C CJK_UNIFIED_IDEOGRAPHS
    char[14]='你' byte=96 \u60 short=20320 \u4F60 CJK_UNIFIED_IDEOGRAPHS
    char[15]='好' byte=125 \u7D short=22909 \u597D CJK_UNIFIED_IDEOGRAPHS

    注意:在新的語(yǔ)言環(huán)境中做以上測(cè)試需要將源程序重新編譯,
    最早的字節(jié)流到字符流的解碼過程從JavaC編譯源文件就開始了,
    這個(gè)測(cè)試和剛才最大的不同在于源文件中的“世界你好”這4個(gè)字是否按中文編碼方式
    編譯導(dǎo)程序里的,而不是按字節(jié)方式編譯成8個(gè)字符(實(shí)際上對(duì)應(yīng)的是8個(gè)字節(jié))在程序里。


    [test 1-2]: getBytes with platform default encoding and decoding as gb2312:
    string=Hello world 世界你好 length=16
    char[0]='H' byte=72 \u48 short=72 \u48 BASIC_LATIN
    char[1]='e' byte=101 \u65 short=101 \u65 BASIC_LATIN
    char[2]='l' byte=108 \u6C short=108 \u6C BASIC_LATIN
    char[3]='l' byte=108 \u6C short=108 \u6C BASIC_LATIN
    char[4]='o' byte=111 \u6F short=111 \u6F BASIC_LATIN
    char[5]=' ' byte=32 \u20 short=32 \u20 BASIC_LATIN
    char[6]='w' byte=119 \u77 short=119 \u77 BASIC_LATIN
    char[7]='o' byte=111 \u6F short=111 \u6F BASIC_LATIN
    char[8]='r' byte=114 \u72 short=114 \u72 BASIC_LATIN
    char[9]='l' byte=108 \u6C short=108 \u6C BASIC_LATIN
    char[10]='d' byte=100 \u64 short=100 \u64 BASIC_LATIN
    char[11]=' ' byte=32 \u20 short=32 \u20 BASIC_LATIN
    char[12]='世' byte=22 \u16 short=19990 \u4E16 CJK_UNIFIED_IDEOGRAPHS
    char[13]='界' byte=76 \u4C short=30028 \u754C CJK_UNIFIED_IDEOGRAPHS
    char[14]='你' byte=96 \u60 short=20320 \u4F60 CJK_UNIFIED_IDEOGRAPHS
    char[15]='好' byte=125 \u7D short=22909 \u597D CJK_UNIFIED_IDEOGRAPHS

    在中文環(huán)境下,解碼和上面缺省的編碼是一致的,因此輸出一致

    [test 1-3]: convert string to UTF8
    string=Hello world 涓栫晫浣犲ソ length=18
    char[0]='H' byte=72 \u48 short=72 \u48 BASIC_LATIN
    char[1]='e' byte=101 \u65 short=101 \u65 BASIC_LATIN
    char[2]='l' byte=108 \u6C short=108 \u6C BASIC_LATIN
    char[3]='l' byte=108 \u6C short=108 \u6C BASIC_LATIN
    char[4]='o' byte=111 \u6F short=111 \u6F BASIC_LATIN
    char[5]=' ' byte=32 \u20 short=32 \u20 BASIC_LATIN
    char[6]='w' byte=119 \u77 short=119 \u77 BASIC_LATIN
    char[7]='o' byte=111 \u6F short=111 \u6F BASIC_LATIN
    char[8]='r' byte=114 \u72 short=114 \u72 BASIC_LATIN
    char[9]='l' byte=108 \u6C short=108 \u6C BASIC_LATIN
    char[10]='d' byte=100 \u64 short=100 \u64 BASIC_LATIN
    char[11]=' ' byte=32 \u20 short=32 \u20 BASIC_LATIN
    char[12]='涓' byte=-109 \uFFFFFF93 short=28051 \u6D93 CJK_UNIFIED_IDEOGRAPHS
    char[13]='栫' byte=43 \u2B short=26667 \u682B CJK_UNIFIED_IDEOGRAPHS
    char[14]='晫' byte=107 \u6B short=26219 \u666B CJK_UNIFIED_IDEOGRAPHS
    char[15]='浣' byte=99 \u63 short=28003 \u6D63 CJK_UNIFIED_IDEOGRAPHS
    char[16]='犲' byte=-78 \uFFFFFFB2 short=29362 \u72B2 CJK_UNIFIED_IDEOGRAPHS
    char[17]='ソ' byte=-67 \uFFFFFFBD short=12477 \u30BD KATAKANA

    其實(shí)我們用于測(cè)試的終端窗口就是一個(gè)GBK字符集的應(yīng)用,
    這個(gè)輸出其實(shí)都是把UNICODE按GBK字符集解碼的效果。



    ========Testing2: reading and decoding from files========
    [test 2-1]: read hello.orig.html: decoding with system default encoding
    string=Hello world 世界你好 length=16
    char[0]='H' byte=72 \u48 short=72 \u48 BASIC_LATIN
    char[1]='e' byte=101 \u65 short=101 \u65 BASIC_LATIN
    char[2]='l' byte=108 \u6C short=108 \u6C BASIC_LATIN
    char[3]='l' byte=108 \u6C short=108 \u6C BASIC_LATIN
    char[4]='o' byte=111 \u6F short=111 \u6F BASIC_LATIN
    char[5]=' ' byte=32 \u20 short=32 \u20 BASIC_LATIN
    char[6]='w' byte=119 \u77 short=119 \u77 BASIC_LATIN
    char[7]='o' byte=111 \u6F short=111 \u6F BASIC_LATIN
    char[8]='r' byte=114 \u72 short=114 \u72 BASIC_LATIN
    char[9]='l' byte=108 \u6C short=108 \u6C BASIC_LATIN
    char[10]='d' byte=100 \u64 short=100 \u64 BASIC_LATIN
    char[11]=' ' byte=32 \u20 short=32 \u20 BASIC_LATIN
    char[12]='世' byte=22 \u16 short=19990 \u4E16 CJK_UNIFIED_IDEOGRAPHS
    char[13]='界' byte=76 \u4C short=30028 \u754C CJK_UNIFIED_IDEOGRAPHS
    char[14]='你' byte=96 \u60 short=20320 \u4F60 CJK_UNIFIED_IDEOGRAPHS
    char[15]='好' byte=125 \u7D short=22909 \u597D CJK_UNIFIED_IDEOGRAPHS

    [test 2-2]: read hello.gb2312.html: decoding as GB2312
    string=Hello world 世界你好 length=16
    char[0]='H' byte=72 \u48 short=72 \u48 BASIC_LATIN
    char[1]='e' byte=101 \u65 short=101 \u65 BASIC_LATIN
    char[2]='l' byte=108 \u6C short=108 \u6C BASIC_LATIN
    char[3]='l' byte=108 \u6C short=108 \u6C BASIC_LATIN
    char[4]='o' byte=111 \u6F short=111 \u6F BASIC_LATIN
    char[5]=' ' byte=32 \u20 short=32 \u20 BASIC_LATIN
    char[6]='w' byte=119 \u77 short=119 \u77 BASIC_LATIN
    char[7]='o' byte=111 \u6F short=111 \u6F BASIC_LATIN
    char[8]='r' byte=114 \u72 short=114 \u72 BASIC_LATIN
    char[9]='l' byte=108 \u6C short=108 \u6C BASIC_LATIN
    char[10]='d' byte=100 \u64 short=100 \u64 BASIC_LATIN
    char[11]=' ' byte=32 \u20 short=32 \u20 BASIC_LATIN
    char[12]='世' byte=22 \u16 short=19990 \u4E16 CJK_UNIFIED_IDEOGRAPHS
    char[13]='界' byte=76 \u4C short=30028 \u754C CJK_UNIFIED_IDEOGRAPHS
    char[14]='你' byte=96 \u60 short=20320 \u4F60 CJK_UNIFIED_IDEOGRAPHS
    char[15]='好' byte=125 \u7D short=22909 \u597D CJK_UNIFIED_IDEOGRAPHS

    [test 2-3]: read hello.utf8.html: decoding as UTF8
    string=Hello world 世界你好 length=16
    char[0]='H' byte=72 \u48 short=72 \u48 BASIC_LATIN
    char[1]='e' byte=101 \u65 short=101 \u65 BASIC_LATIN
    char[2]='l' byte=108 \u6C short=108 \u6C BASIC_LATIN
    char[3]='l' byte=108 \u6C short=108 \u6C BASIC_LATIN
    char[4]='o' byte=111 \u6F short=111 \u6F BASIC_LATIN
    char[5]=' ' byte=32 \u20 short=32 \u20 BASIC_LATIN
    char[6]='w' byte=119 \u77 short=119 \u77 BASIC_LATIN
    char[7]='o' byte=111 \u6F short=111 \u6F BASIC_LATIN
    char[8]='r' byte=114 \u72 short=114 \u72 BASIC_LATIN
    char[9]='l' byte=108 \u6C short=108 \u6C BASIC_LATIN
    char[10]='d' byte=100 \u64 short=100 \u64 BASIC_LATIN
    char[11]=' ' byte=32 \u20 short=32 \u20 BASIC_LATIN
    char[12]='世' byte=22 \u16 short=19990 \u4E16 CJK_UNIFIED_IDEOGRAPHS
    char[13]='界' byte=76 \u4C short=30028 \u754C CJK_UNIFIED_IDEOGRAPHS
    char[14]='你' byte=96 \u60 short=20320 \u4F60 CJK_UNIFIED_IDEOGRAPHS
    char[15]='好' byte=125 \u7D short=22909 \u597D CJK_UNIFIED_IDEOGRAPHS

    結(jié)論:如果后臺(tái)數(shù)據(jù)采用UNICODE方式的存儲(chǔ)
    然后根據(jù)需要指定字符集編碼、解碼方式,則應(yīng)用幾乎可以不受前端應(yīng)用所處
    環(huán)境字符集設(shè)置的影響

    試驗(yàn)2的一些結(jié)論:

    1. 所有的應(yīng)用都是按照字節(jié)流=>字符流=>字節(jié)流方式進(jìn)行的處理的:
      byte_stream ==[input decoding]==> unicode_char_stream ==[output encoding]==> byte_stream;
    2. 在Java字節(jié)流到字符流(或者反之)都是含有隱含的解碼處理的(缺省是按照系統(tǒng)缺省編碼方式);
    3. 最早的字節(jié)流解碼過程從javac的代碼編譯就開始了;
    4. Java中的字符character存儲(chǔ)單位是雙字節(jié)的UNICODE;

    試驗(yàn)3:WEB應(yīng)用中的輸入輸出中的編碼問題:Java是為做國(guó)際化應(yīng)用設(shè)計(jì)的,Servlet應(yīng)根據(jù)瀏覽器語(yǔ)言設(shè)置自動(dòng)切換字符集配置

    首先一個(gè)概念:即使是基于Java的WEB應(yīng)用,在服務(wù)器和客戶端之間傳遞的仍然是字節(jié)流,比如我從一個(gè)中文客戶端的瀏覽器表單中提交“世界你好”這4個(gè)中文字到服務(wù)器時(shí):首先瀏覽器按照GBK方式編碼成字節(jié)流CA C0 BD E7 C4 E3 BA C3,然后8個(gè)字節(jié)按照URLEncoding的規(guī)范轉(zhuǎn)成:%CA%C0%BD%E7%C4%E3%BA%C3,服務(wù)器端的Servlet接收到請(qǐng)求后應(yīng)該按什么解碼處理,輸出時(shí)又應(yīng)該按什么方式編碼行字節(jié)流呢?

    在目前的Servlet的規(guī)范中,如果不指定的話通過WEB提交時(shí)的輸入ServletRequest和輸出時(shí)的ServletResponse缺 省都是ISO-8859-1方式編/碼解碼的(注意,這里的編碼/解碼方式是和操作系統(tǒng)環(huán)境中的語(yǔ)言環(huán)境是無關(guān)的)。因此,即使服務(wù)器操作系統(tǒng)的語(yǔ)言環(huán)境 是中文,上面輸入的請(qǐng)求仍然按英文解碼成8個(gè)UNICODE字符,輸出時(shí)仍按照英文再編碼成8個(gè)字節(jié),雖然這樣在瀏覽器端如果設(shè)置是中文能夠正確顯示,但 實(shí)際上讀寫的是“字節(jié)”,正確的方式是應(yīng)該根據(jù)客戶端瀏覽器設(shè)置ServletRequest和ServletResponse用相應(yīng)語(yǔ)言的編碼方式進(jìn)行 輸入解碼/輸入編碼,HelloUnicodeServlet.java就是這樣一個(gè)監(jiān)測(cè)客戶端瀏覽器語(yǔ)言設(shè)置的例子:

    當(dāng)根據(jù)瀏覽器的頭信息中的"Accept-Language"為zh-cn(中文)時(shí),設(shè)置請(qǐng)求的解碼方式和輸出的字符集編碼方式使用GBK:

            //auto detect broswer's languages
    String clientLanguage = req.getHeader("Accept-Language");

    //for Simplied Chinese
    if ( clientLanguage.equals("zh-cn") ) {
    req.setCharacterEncoding("GBK");
    res.setContentType("text/html; charset=GBK");
    }
    輸出為:
    '世界你好' length=4
    ServletRequest's Charset Encoding = GBK
    ServletResponse's Charset Encoding = GBK
    char[0]='世' byte=22 \u16 short=19990 \u4E16 CJK_UNIFIED_IDEOGRAPHS
    char[1]='界' byte=76 \u4C short=30028 \u754C CJK_UNIFIED_IDEOGRAPHS
    char[2]='你' byte=96 \u60 short=20320 \u4F60 CJK_UNIFIED_IDEOGRAPHS
    char[3]='好' byte=125 \u7D short=22909 \u597D CJK_UNIFIED_IDEOGRAPHS

    再做一個(gè)試驗(yàn):把程序開頭部分的瀏覽器自動(dòng)檢測(cè)功能注釋掉,再次的輸出結(jié)果就是和目前很多應(yīng)用一樣其實(shí)是按ISO-8859-1方式解碼/編碼的“字節(jié)應(yīng)用”了:

    '世界你好' length=8
    ServletRequest's Charset Encoding = null
    ServletResponse's Charset Encoding = ISO-8859-1
    char[0]='? byte=-54 \uFFFFFFCA short=202 \uCA LATIN_1_SUPPLEMENT
    char[1]='? byte=-64 \uFFFFFFC0 short=192 \uC0 LATIN_1_SUPPLEMENT
    char[2]='? byte=-67 \uFFFFFFBD short=189 \uBD LATIN_1_SUPPLEMENT
    char[3]='? byte=-25 \uFFFFFFE7 short=231 \uE7 LATIN_1_SUPPLEMENT
    char[4]='? byte=-60 \uFFFFFFC4 short=196 \uC4 LATIN_1_SUPPLEMENT
    char[5]='? byte=-29 \uFFFFFFE3 short=227 \uE3 LATIN_1_SUPPLEMENT
    char[6]='? byte=-70 \uFFFFFFBA short=186 \uBA LATIN_1_SUPPLEMENT
    char[7]='? byte=-61 \uFFFFFFC3 short=195 \uC3 LATIN_1_SUPPLEMENT
    雖然這樣的輸出結(jié)果如果在瀏覽器中設(shè)置用中文字符集也能正確顯示,但實(shí)際上處理的已經(jīng)是“字節(jié)”而不是處理中文“字符”了。ServletRequest 和 ServletResponse 缺省使用ISO-8859-1字符集解碼/編碼的具體定義請(qǐng)參考:
    http://java.sun.com/products/servlet/2.3/javadoc/javax/servlet/ServletRequest.html#setCharacterEncoding(java.lang.String)

    http://java.sun.com/products/servlet/2.3/javadoc/javax/servlet/ServletResponse.html#setContentType()

    以前能夠配置讓一個(gè)WEB應(yīng)用能夠在GBK方式編碼的中文Windows2000服務(wù)器上和按ISO-8859-1方式編碼的GNU/Linux上 都能夠正確的顯示中文一直讓我迷惑了很久。我仔細(xì)想了一下,后來終于想明白了,在一個(gè)國(guó)際化的應(yīng)用中:ServletRequest和 ServletResponse的編碼/解碼方式的確不應(yīng)該根據(jù)服務(wù)器設(shè)置成固定的字符集,而應(yīng)該是面向客戶端語(yǔ)言環(huán)境進(jìn)行輸入/輸出編碼方式的自適應(yīng)。一個(gè)按照國(guó)際化規(guī)范設(shè)計(jì)的WEB應(yīng)用中:

    • 在Servlet的源代碼中盡量不要有中文:因?yàn)樵贛VC模式中,Servlet主要是控制器(C)的角色,因此,應(yīng)該通過 ResourceBundle機(jī)制由Servlet控制轉(zhuǎn)向到相應(yīng)的顯示器(JSP或者XSLT)中,所以應(yīng)該將與本地界面語(yǔ)言相關(guān)的界面顯示的部分從 Servlet和后臺(tái)的模塊中完全剝離出來,放到相應(yīng)的ResourceBundle文件中或者XSLT文件中。這樣源程序里完全是英文,編譯時(shí)完全不需要考慮字符集的問題。

      如果Servlet實(shí)在需要包含中文,則需要設(shè)置應(yīng)用服務(wù)器的Javac編譯選項(xiàng),加上-encoding選項(xiàng)成系統(tǒng)缺省的字符集,如果把用中文編寫的字符按照英文方式解碼編譯,然后再按照英文方式輸出,雖然結(jié)果表面正確,實(shí)際上都成了面向“字節(jié)”編程。
    • 在Servlet層,應(yīng)該像GOOGLE搜索引擎那樣,設(shè)計(jì)成能夠根據(jù)客戶端瀏覽器的語(yǔ)言環(huán)境自適應(yīng)輸出,為了判斷瀏覽器的語(yǔ)言Servlet中應(yīng)該有類似以下的代碼:
          public void doGet (HttpServletRequest req, HttpServletResponse res)
      throws ServletException, IOException {
      //從HTTP請(qǐng)求的頭信息中獲取客戶端的語(yǔ)言設(shè)置
      String clientLanguage = req.getHeader("Accept-Language");

      //簡(jiǎn)體中文瀏覽器
      if ( clientLanguage.equals("zh-cn") ) {
      req.setCharacterEncoding("GBK");
      res.setContentType("text/html; charset=GBK");
      }
      //繁體中文瀏覽器
      else if ( clientLanguage.equals("zh-tw") ) {
      req.setCharacterEncoding("BIG5");
      res.setContentType("text/html; charset=BIG5");
      }
      //日文瀏覽器
      else if ( clientLanguage.equals("jp") ) {
      req.setCharacterEncoding("SJIS");
      res.setContentType("text/html; charset=SJIS");
      }
      //缺省認(rèn)為是英文瀏覽器
      else {
      req.setCharacterEncoding("ISO-8859-1");
      res.setContentType("text/html; charset=ISO-8859-1");
      }
      ...
      //設(shè)置好request的解碼方式和response的編碼方式后,進(jìn)行后續(xù)的操作。
      //比如再轉(zhuǎn)向到HelloWorld.gbk.jsp HelloWorld.big5.jsp HelloWorld.jis.jsp等
      }

    而SERVLET缺省將字符集設(shè)置為ISO-8859-1也許是標(biāo)準(zhǔn)制定者認(rèn)為英文的瀏覽器占大多數(shù)吧(而且按照ISO-8859-1方式輸出界面往往也是正確的)。

    結(jié)論:

    過以上幾個(gè)Java試驗(yàn)程序得出的一些結(jié)論:

    • Java環(huán)境是基于操作系統(tǒng)上的一個(gè)虛擬機(jī)應(yīng)用,因此,如果操作系統(tǒng)遵循國(guó)際化規(guī)范:JVM的缺省編碼方式可以通過修改操作系統(tǒng) 的LOCALE設(shè)置實(shí)現(xiàn)。對(duì)于一個(gè)Java應(yīng)用來說,只要將LINUX的缺省編碼方式設(shè)置成GBK,其文字編碼處理應(yīng)該和中文Windows平臺(tái)上的表現(xiàn) 是一致的。
          redhat 6.X使用linux內(nèi)核的是基于glibc2.1.X,不支持中文LOCALE,因此無法通過改變LOCALE設(shè)置改變JVM的缺省編碼方式,linux內(nèi)核2.4開始基于glibc.2.2.x,對(duì)中文LOCALE有了比較好的支持。
    • 不同的JVM對(duì)字符集的支持程度不同:
          比如:IBM的JVM1.3.0開始支持GB18030,SUN的JVM從1.4開始支持GB18030
    • 正確的編碼方式不一定表示能正確的顯示,正確的顯示還要需要相應(yīng)的前端顯示系統(tǒng)(字庫(kù))的支持
          但對(duì)于Linux上的服務(wù)應(yīng)用來說,往往只要能確認(rèn)字符正確的按照指定的方式編碼就夠了
    • 如果應(yīng)用的是基于UNICODE的編碼方式處理并使用UTF8字符集做集中存儲(chǔ),這樣最便于根據(jù)客戶端語(yǔ)言環(huán)境做本地化輸出;

    根據(jù)以上結(jié)論,設(shè)計(jì)一個(gè)適應(yīng)多語(yǔ)言環(huán)境的應(yīng)用,可以考慮一下2個(gè)應(yīng)用處理模式:

    • (客戶端應(yīng)用或本地化應(yīng)用)根據(jù)LOCALE,讓Java應(yīng)用根據(jù)系統(tǒng)LOCALE的缺省的字符集設(shè)置進(jìn)行切換,按系統(tǒng)缺省的字符集進(jìn)行編碼解碼,減少應(yīng)用在編碼處理上的復(fù)雜程度。
      輸入字節(jié)流 ==>按系統(tǒng)語(yǔ)言字符集設(shè)置將字節(jié)流解碼==> UNICODE處理 ==> 按系統(tǒng)語(yǔ)言字符集設(shè)置將UNICODE編碼成字節(jié)流 ==> 輸出字節(jié)流
        
    • (服務(wù)器端或跨語(yǔ)言平臺(tái)應(yīng)用):在應(yīng)用的最外端:數(shù)據(jù)輸入輸出判斷用戶語(yǔ)言環(huán)境,核心按照UNICODE方式處理存儲(chǔ)。可以把各種區(qū)域性的字符集(GB2312 BIG5)看成是UNICODE的一個(gè)子集。UNICODE存儲(chǔ)的數(shù)據(jù)可以方便的轉(zhuǎn)換成任意字符集。
      應(yīng)用使用UTF8方式存儲(chǔ)雖然要增加了存儲(chǔ)空間,但也可以大大簡(jiǎn)化前端應(yīng)用本地化(i10n)的復(fù)雜程度。    
      簡(jiǎn)體中文輸入 繁體中文輸入                 簡(jiǎn)體中文輸出 繁體中文輸出
      \ / \ /
      判斷用戶語(yǔ)言環(huán)境:解碼 判斷用戶語(yǔ)言環(huán)境:編碼
      \ /
      中間處理過程:UNICODE
      |
      UTF8編碼存儲(chǔ)

    隨著UNICODE被愈來愈多的系統(tǒng)和平臺(tái)支持:Python Perl Glibc等,但我們應(yīng)該珍惜一開始就按照國(guó)際化規(guī)范設(shè)計(jì)Java,并將其和新發(fā)展起來的XML規(guī)范相配合,相信符合國(guó)際化規(guī)范的應(yīng)用設(shè)計(jì)從長(zhǎng)遠(yuǎn)來看會(huì)展現(xiàn)出更多的優(yōu)勢(shì)。

    TODO:
    數(shù)據(jù)庫(kù)應(yīng)用中的字符集問題試驗(yàn):MySQL Oracle JDBC

    參考文檔:
    Java的國(guó)際化設(shè)計(jì)
    http://java.sun.com/docs/books/tutorial/i18n/index.html

    Linux 國(guó)際化本地化和中文化
    http://www.linuxforum.net/doc/i18n-new.html

    Linux 程序員必讀:中文化與GB18030標(biāo)準(zhǔn)
    http://www.ccidnet.com/tech/os/2001/07/31/58_2811.html

    Unicode FAQ
    http://www.cl.cam.ac.uk/~mgk25/unicode.html
    http://www.linuxforum.net/books/UTF-8-Unicode.html (中文版)

    Java 編程技術(shù)中漢字問題的分析及解決
    http://www-900.ibm.com/developerWorks/cn/java/java_chinese/index.shtml

    漢字的編碼方式:
    http://www.unihan.com.cn/cjk/ana17.htm

    不同版本的JVM支持的編碼方式
    http://java.sun.com/j2se/1.3/docs/guide/intl/encoding.doc.html
    http://java.sun.com/j2se/1.4/docs/guide/intl/encoding.doc.html

    附錄:

    A. The Unicode 2.0 Character Set

    Characters

    Description

    \u0000 - \u1FFF

    Alphabets

    \u0020 - \u007F

    Basic Latin

    \u0080 - \u00FF

    Latin-1 supplement

    \u0100 - \u017F

    Latin extended-A

    \u0180 - \u024F

    Latin extended-B

    \u0250 - \u02AF

    IPA extensions

    \u02B0 - \u02FF

    Spacing modifier letters

    \u0300 - \u036F

    Combining diacritical marks

    \u0370 - \u03FF

    Greek

    \u0400 - \u04FF

    Cyrillic

    \u0530 - \u058F

    Armenian

    \u0590 - \u05FF

    Hebrew

    \u0600 - \u06FF

    Arabic

    \u0900 - \u097F

    Devanagari

    \u0980 - \u09FF

    Bengali

    \u0A00 - \u0A7F

    Gurmukhi

    \u0A80 - \u0AFF

    Gujarati

    \u0B00 - \u0B7F

    Oriya

    \u0B80 - \u0BFF

    Tamil

    \u0C00 - \u0C7F

    Telugu

    \u0C80 - \u0CFF

    Kannada

    \u0D00 - \u0D7F

    Malayalam

    \u0E00 - \u0E7F

    Thai

    \u0E80 - \u0EFF

    Lao

    \u0F00 - \u0FBF

    Tibetan

    \u10A0 - \u10FF

    Georgian

    \u1100 - \u11FF

    Hangul Jamo

    \u1E00 - \u1EFF

    Latin extended additional

    \u1F00 - \u1FFF

    Greek extended

    \u2000 - \u2FFF

    Symbols and punctuation

    \u2000 - \u206F

    General punctuation

    \u2070 - \u209F

    Superscripts and subscripts

    \u20A0 - \u20CF

    Currency symbols

    \u20D0 - \u20FF

    Combining diacritical marks for symbols

    \u2100 - \u214F

    Letterlike symbols

    \u2150 - \u218F

    Number forms

    \u2190 - \u21FF

    Arrows

    \u2200 - \u22FF

    Mathematical operators

    \u2300 - \u23FF

    Miscellaneous technical

    \u2400 - \u243F

    Control pictures

    \u2440 - \u245F

    Optical character recognition

    \u2460 - \u24FF

    Enclosed alphanumerics

    \u2500 - \u257F

    Box drawing

    \u2580 - \u259F

    Block elements

    \u25A0 - \u25FF

    Geometric shapes

    \u2600 - \u26FF

    Miscellaneous symbols

    \u2700 - \u27BF

    Dingbats

    \u3000 - \u33FF

    CJK auxiliary

    \u3000 - \u303F

    CJK symbols and punctuation

    \u3040 - \u309F

    Hiragana

    \u30A0 - \u30FF

    Katakana

    \u3100 - \u312F

    Bopomofo

    \u3130 - \u318F

    Hangul compatibility Jamo

    \u3190 - \u319F

    Kanbun

    \u3200 - \u32FF

    Enclosed CJK letters and months

    \u3300 - \u33FF

    CJK compatibility

    \u4E00 - \u9FFF

    CJK unified ideographs: Han characters used in China, Japan, Korea, Taiwan, and Vietnam

    \uAC00 - \uD7A3

    Hangul syllables

    \uD800 - \uDFFF

    Surrogates

    \uD800 - \uDB7F

    High surrogates

    \uDB80 - \uDBFF

    High private use surrogates

    \uDC00 - \uDFFF

    Low surrogates

    \uE000 - \uF8FF

    Private use

    \uF900 - \uFFFF

    Miscellaneous

    \uF900 - \uFAFF

    CJK compatibility ideographs

    \uFB00 - \uFB4F

    Alphabetic presentation forms

    \uFB50 - \uFDFF

    Arabic presentation forms-A

    \uFE20 - \uFE2F

    Combing half marks

    \uFE30 - \uFE4F

    CJK compatibility forms

    \uFE50 - \uFE6F

    Small form variants

    \uFE70 - \uFEFE

    Arabic presentation forms-B

    \uFEFF

    Specials

    \uFF00 - \uFFEF

    Halfwidth and fullwidth forms

    \uFFF0 - \uFFFF

    Specials

     

    原文出處:<a >http://www.chedong.com/tech/hello_unicode.html</a>
    <<返回

    http://docs.huihoo.com/column/chedong/hello_unicode.html

    posted on 2010-01-13 17:34 卓凡 閱讀(536) 評(píng)論(1)  編輯  收藏

    評(píng)論

    # re: (轉(zhuǎn))Java中文處理學(xué)習(xí)筆記——Hello Unicode 2012-12-03 11:42 avi9111

    java這是庸人自擾

    本來就不清不楚

    看了你的文章更是云里霧里

    還有一堆人像你這樣想把問題說明白

    可根本說不明白,而且實(shí)際寫代碼的時(shí)候更是完全用不上  回復(fù)  更多評(píng)論   


    只有注冊(cè)用戶登錄后才能發(fā)表評(píng)論。


    網(wǎng)站導(dǎo)航:
     

    導(dǎo)航

    統(tǒng)計(jì)

    常用鏈接

    留言簿

    隨筆檔案

    文章分類

    文章檔案

    搜索

    最新評(píng)論

    閱讀排行榜

    評(píng)論排行榜

    主站蜘蛛池模板: 青青草a免费线观a| 蜜臀98精品国产免费观看| a级大片免费观看| 免费国产黄网站在线观看视频| 1000部无遮挡拍拍拍免费视频观看| 中国在线观看免费高清完整版| 国产免费私拍一区二区三区| 精品国产亚洲一区二区在线观看| 亚洲Av无码专区国产乱码DVD | 亚洲性无码一区二区三区 | 2017亚洲男人天堂一| 色欲色欲天天天www亚洲伊| 精品久久久久久国产免费了| **一级毛片免费完整视| 国产青草视频在线观看免费影院| 国产日产亚洲系列| 亚洲精品在线不卡| 免费的黄网站男人的天堂| 免费国产99久久久香蕉| 国产免费av片在线看| 中文字幕亚洲电影| 亚洲国产中文在线二区三区免| 国产亚洲情侣久久精品| 最近中文字幕完整免费视频ww| 国产免费爽爽视频免费可以看| 亚洲免费视频在线观看| 色窝窝亚洲av网| 一级毛片免费观看不卡视频| 精品国产一区二区三区免费看| 久久久久久久综合日本亚洲| 亚洲国产精品99久久久久久| 在线播放免费人成毛片乱码| 最新69国产成人精品免费视频动漫 | 久久丫精品国产亚洲av| 亚洲AV无码专区在线厂| 免费一级毛片无毒不卡| 免费人妻无码不卡中文字幕18禁| 亚洲精品在线网站| 中文字幕在线成人免费看| 午夜一级免费视频| 亚洲一区二区在线免费观看|