Java中文處理學習筆記——Hello Unicode (轉)

worldblog發表於2007-12-13
Java中文處理學習筆記——Hello Unicode (轉)[@more@]

中文處理學習筆記——Hello Unicode

作者: 車東 chedong@bigfoot.com

最後:

版權宣告:可以任意轉載,轉載時請務必以超連結形式標明文章原始出處和作者資訊及本宣告

關鍵詞: java mutlibyte encoding locale i18n i10n chinese  ISO-8859-1 GB2312 BIG5 GBK UNICODE

內容摘要:

    不知道你有沒有這樣的感受:為什麼很少有亂碼問題而用Java做應用卻這麼麻煩呢?為什麼在上能用簡體中文查到繁體中文,甚至日文的結果?而且用Google的時候發現它居然能自動根據我使用的語言選擇自動調出中文介面?

    很多國際化應用的讓我理解了這麼一個道理:Unicode是為更方便的做國際化應用設計的,而Java核心的字元是基於UNICODE的,這一機制為應用提供了對中文“字”的控制(而不是位元組)。但如果不仔細理解其中的規範,這種自由反而會成為累贅,從而導致更多的亂碼問題:

    1. 的環境設定和支援的編碼方式;

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

    假設一個字元就是棋盤上的一個棋子,有其固定的座標,如果需要區別所有的字元,就需要有足夠的棋格容納不同的“字元”。 

    英文和歐洲其他語言的單位元組字符集(SingleByte Charsets):
    首先對於ISO-8859系列的字符集都想象成一個:2^8 = 16 * 16 = 256個格子的棋盤,這樣所有的西文字元(英文)用這樣一個16×16的座標系就基本可以覆蓋全了。而英文實際上只用其中小於128(x80)的部分就夠了。利用大於128部分的空間的不同定義規則形成了真對其他歐洲語言的擴充套件字符集:ISO-8859-2 ISO-8859-4等……

    ISO-8859-1
    ISO-8859-7
    其他語言
    英文其他西歐字元   ōē
    英文希臘字元
      μγ 英文其他單位元組  字符集


    GB2312 BIG5 SJIS等多位元組字符集(MultiByte Charsets):

    對於亞洲語言來說:漢字這麼多,用這麼一個256格的小棋盤肯定放不下,所以要區別成千上萬的漢字解決辦法就是用2個位元組(座標)來定位一個“字”在棋盤上的位置,將以上規則做一個擴充套件:

    • 如果第1個字元是小於128(x80)的仍和英文字符集編碼方式保持相容;
    • 如果第1個字元是大於128(x80)的,就當成是漢字的第1個位元組,這個自己和後面緊跟的1個位元組組成一個漢字;

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

    簡體中文
    日文SJIS
    繁體中文
    英文簡
    體   中
       文 英文日
     文        英文

     繁   體
    中文

    由此可以看出,所有這些從ASCII擴充套件式的編碼方式中:英文部分都是相容的,但擴充套件部分的編碼方式是不相容的,雖然很多字在3種體系中寫法一致(比如“中文”這2個字)但在相應字符集中的座標不一致,所以GB2312編寫的頁面用BIG5看就變得面目全非了。而且有時候經常在瀏覽其他非英語國家的頁面時(比如包含有德語的人名時)經常出現奇怪的漢字,其實就是擴充套件位的編碼衝突造成的。

    我把GBK和GB18030理解成一個小UNICODE:GBK字符集是GB2312的擴充套件(K),GBK裡大約有貳萬玖仟多個字元,除了保持和GB2312相容外,繁體中文字,甚至連日文的假名字元也能顯示。而GB18030-2000則是一個更復雜的字符集,採用變長位元組的編碼方式,能夠支援更多的字元。關於漢字的編碼方式比較詳細的定義規範可以參考:

    ASCII(英文) ==> 西歐文字 ==> 東歐字符集(俄文,希臘語等) ==> 東亞字符集(GB2312 BIG5 SJIS等)==> 擴充套件字符集GBK GB18030這個發展過程基本上也反映了字符集標準的發展過程,但這麼隨著時間的推移,尤其是網際網路讓跨語言的資訊的互動變得越來越多的時候,太多多針對本地語言的編碼標準的出現導致一個應用的國際化變得成本非常高。尤其是你要編寫一個同時包含法文和簡體中文的文件,這時候一般都會想到要是用一個通用的字符集能夠顯示所有語言的所有文字就好了,而且這樣做應用也能夠比較方便的國際化,為了達到這個目標,即使應用犧牲一些空間和程式也是非常值得的。UNICODE就是這樣一個通用的解決方案。

    UNICODE雙位元組字符集
    所以你可以把UNICODE想象成這樣:讓所有的字元(包括英文)都用2個位元組(2個8位)表示,這樣就有了一個2^(8*2) = 256 * 256 = 65536個格子的大棋盤。在這個棋盤中,這樣中(簡繁)日韓(還包括越南)文字作為CJK字符集都放在一定的區位內,為了減少重複,各種語言中寫法一樣的字共享一個“棋格”。詳細的區位見

    Unicode:(DoubleByte Charsets)

    西 C中 其 歐 J日 它 英 K韓 語 文  言

     

    什麼還要有UTF-8?畢竟網際網路70%以上的資訊仍然是英文。如果連英文都用2個位元組存取(UCS-2),空間浪費不就太多了?所謂UTF-8就是這樣一個為了提高英文存取效率的字符集轉換格式:Unicode Tranormation Fo8-bit form。用UTF-8,UNICODE的2位元組字元用變長個(1-3個位元組)表示:

    1. 對英文,仍然和ASCII一樣用1個位元組表示,這個位元組的值小於128(x80);
    2. 對其他語言的用一個值位於128-256之間的位元組開始,再加後面緊跟的2個位元組表示,一個字元一共是3個位元組;

    因此,在應用中程式處理過程中所有字元都是16位(雙位元組),但在存取轉換成位元組流時使用UTF-8格式轉換,對於英文字元來說和原來用ASCII方式存取時相比大小仍然是一樣的,而對中文來說和原來的GB2312編碼方式相比,大小為:(3位元組/2位元組)=1.5倍

    小節:

    假設英文字符集是一個16×16的棋盤,麼其他語言的字符集就是把高位區重新分割的(> 128)的中等棋盤,多種字符集之間互不相容而UNICODE本身就相當於一個256×256的大棋盤,透過一定規則將英文和其他所有語言的字元都包含在內。

    語言環境設定對Java應用預設編碼方式的影響

    為了瞭解Java應用的編碼處理的機制,首先要了解作業系統對JVM預設編碼方式的影響,因此我做了一個,用於列印顯示不同系統下JVM的屬性和系統支援的LOCALE。程式很簡單:

    /*
    * Copyright (c) 2002 chedong@bigfoot.com
    * $Id: Env.java,v 1.1 2002/07/30 09:48:12 chedong E$
    */

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

    /**
    * 目的:
    * 顯示環境變數和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屬性,這個屬性確定了JVM的預設的編碼/解碼方式:從而影響應用中所有位元組流==>字元流的解碼方式 ,字元流==>位元組流的編碼方式。

      LINUX下的LOCALE可以透過 LANG=zh_CN; LC_ALL=zh_CN.GBK; export LANG LC_ALL 設定。locale 命令可以顯示系統當前的環境設定
      的LOCALE可以透過 控制皮膚==>區域設定 設定實現

    /Linux 2.4.x (1.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
    (J2SE1.3.0) 
    區域設定:中國  中文
    Windows 2000(J2SE1.3.0) 
    區域設定:英國 英文

    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 King)
    en_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 Dutchherlands)
    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/1.3.1_04//lib/i386
    java.vm.version=1.3.1_04-b02
    java.vm.vendor=Sun Microsystems Inc.
    java.vendor.url=
    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 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.=cgi-bin/bugreport... sun..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 英文 (美國)
    ar 阿拉伯文
    ar_AE 阿拉伯文 (阿拉伯聯合大公國)
    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 捷克文 (捷克共和國)
    da 丹麥文
    da_DK 丹麥文 (丹麥)
    de 德文
    de_AT 德文 (奧地利)
    de_AT_EURO 德文 (奧地利,Euro)
    de_CH 德文 (瑞士)
    de_DE 德文 (德國)
    de_DE_EURO 德文 (德國,Euro)
    de_LU 德文 (盧森堡)
    de_LU_EURO 德文 (盧森堡,Euro)
    el 希臘文
    el_GR 希臘文 (希臘)
    en_AU 英文 (澳大利亞)
    en_CA 英文 (加拿大)
    en_GB 英文 (英國)
    en_IE 英文 (愛爾蘭)
    en_IE_EURO 英文 (愛爾蘭,Euro)
    en_NZ 英文 (紐西蘭)
    en_ZA 英文 (南非)
    es 西班牙文
    es_BO 西班牙文 (玻利維亞)
    es_AR 西班牙文 (阿根廷)
    es_CL 西班牙文 (智利)
    es_CO 西班牙文 (哥倫比亞)
    es_CR 西班牙文 (哥斯大黎加)
    es_DO 西班牙文 (多明尼加共和國)
    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 西班牙文 (委內瑞拉)
    et_EE 愛沙尼亞文 (愛沙尼亞)
    fi 芬蘭文
    fi_FI 芬蘭文 (芬蘭)
    fi_FI_EURO 芬蘭文 (芬蘭,Euro)
    fr 法文
    fr_BE 法文 (比利時)
    fr_BE_EURO 法文 (比利時,Euro)
    fr_CA 法文 (加拿大)
    fr_CH 法文 (瑞士)
    fr_FR 法文 (法國)
    fr_FR_EURO 法文 (法國,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 馬其頓文 (馬其頓王國)
    nl 荷蘭文
    nl_BE 荷蘭文 (比利時)
    nl_BE_EURO 荷蘭文 (比利時,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 泰文 (泰國)
    tr 土耳其文
    tr_TR 土耳其文 (土耳其)
    uk 烏克蘭文
    uk_UA 烏克蘭文 (烏克蘭)
    zh 中文
    zh_CN 中文 (中國)
    zh_HK 中文 (香港)
    zh_TW 中文 (臺灣)
    ======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=
    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=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 韓文 (大韓民國)
    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 中文 (中華人民共和國)
    zh_HK 中文 (香港)
    zh_TW 中文 (臺灣)
    ======System property========
    -- listing properties --
    java.runtime.name=Java(TM) 2 Runtime Environment, Stand...
    sun.boot.library.path=C:PROGRAM FILESJavaSOFTJRE1.3.0_0...
    java.vm.version=1.3.0_02
    java.vm.vendor=Sun Microsystems Inc.
    java.vendor.url=
    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:javasrcchar_test
    java.runtime.version=1.3.0_02
    java.awt.graphicsenv=sun.awt.GraphicsEnvironment
    os.arch=x86
    java.io.tmpdir=D:TEMP
    line.separator=

    java.vm.specification.vendor=Sun Microsystems Inc.
    java.awt.fonts=
    os.name=
    java.library.path=C:WINDOWS;.;C:WINDOWSSYSTEM;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:javaclasses java.vm.specification.version=1.0 java.home=C:PROGRAM FILESJavaSOFTJRE1.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 FILESJavaSOFTJRE1.3.0_0... sun.boot.class.path=C:PROGRAM FILESJavaSOFTJRE1.3.0_0... java.vendor=Sun Microsystems Inc. file.separator= java.vendor.url.bug=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 FILESJavaSOFTJRE1.3.0_0...
    java.vm.version=1.3.0_02
    java.vm.vendor=Sun Microsystems Inc.
    java.vendor.url=
    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:javasrcchar_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:WINDOWSSYSTEM;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:javaclasses java.vm.specification.version=1.0 java.home=C:PROGRAM FILESJavaSOFTJRE1.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 FILESJavaSOFTJRE1.3.0_0... sun.boot.class.path=C:PROGRAM FILESJavaSOFTJRE1.3.0_0... java.vendor=Sun Microsystems Inc. file.separator= java.vendor.url.bug=cgi-bin/bugreport... sun.cpu.endian=little sun.io.unicode.encoding=UnicodeLittle user.region=GB sun.cpu.isalist=pentium i486 i386

    
    

    結論1:

    JVM的預設編碼方式由系統的“本地語言環境”設定確定,和作業系統的型別無關所以當設定成相同的LOCALE時,Linux和Windows下的預設編碼方式是沒有區別的(可以認為cp1252=ISO-8859-1都是一樣的西文編碼方式,只包含255以下的拉丁字元),因此後面的測試2我只列出了GNU/Linux下LOCALE分別設定成zh_CN和en_US的測試結果輸出。以下測試如果在Windows下分別按照不同的區域和字符集設定後試驗的輸出是一樣的。

    透過這個程式,演示說明"Hello world 世界你好"這個字串(16個字元)在不同預設系統編碼方式下的處理效果。在編碼/解碼的每個步驟之後,都列印出了相應字串每個字元(Charactor)的byte值,short值和所在的UNICODE區間。

    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步:在英文編碼環境下,雖然螢幕上正確的顯示了中文,
    但實際上它列印的是“半個”漢字,將結果寫入第1個 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_OGRAPHS 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 按系統預設編碼重新變成位元組流,然後按照GB2312方式解碼,這裡雖然列印出的是問號
    (因為當前的英文環境下系統對於255以上的字元是不知道用什麼字元表示的,因此全部用?顯示)
    但從相應的UNICODE MAP和SHORT值我們可以知道字元是正確的中文

    但下一步的寫入第2個檔案html.gb2312.html,
    沒有指定編碼方式(按系統預設的ISO-8859-1編碼方式),
    因此從後面的測試2-2讀取的結果是真的'?'了
    [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個試驗,將字元流按照UTF8方式編碼後,寫入第3個測試檔案hello.utf8.html,
    我們可以看到UTF8對英文沒有影響,但對於其他文字使用了3位元組編碼方式,
    因此比GB2312編碼方式的要大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 按系統從中間儲存hello.orig.html檔案中讀取相應檔案,
    雖然是按位元組方式(半個“字”)讀取的,但由於能完整的還原,因此輸出顯示沒有錯誤。
    其實PHP等應用很少出現字符集問題其實就是這個原因,全程都是按位元組流方式處理,
    很好的還原了輸入,但這樣處理的同時也失去了對字元的控制 [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 最慘的就是輸出的時候這些'?'真的是問號char(63)了,
    資料如果是這樣就真的沒救了 [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! 字元雖然顯示為'?',但實際上字元的解碼是正確的,
    從相應的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

    注意:在新的語言環境中做以上測試需要將源程式重新編譯,
    最早的位元組流到字元流的解碼過程從JavaC編譯原始檔就開始了,
    這個測試和剛才最大的不同在於原始檔中的“世界你好”這4個字是否按中文編碼方式
    編譯導程式裡的,而不是按位元組方式編譯成8個字元(實際上對應的是8個位元組)在程式裡。
    [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 在中文環境下,解碼和上面預設的編碼是一致的,因此輸出一致 [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 其實我們用於測試的終端視窗就是一個GBK字符集的應用,
    這個輸出其實都是把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 結論:如果後臺資料採用UNICODE方式的儲存
    然後根據需要指定字符集編碼、解碼方式,則應用幾乎可以不受前端應用所處
    環境字符集設定的影響

     
    

    試驗2的一些結論:

    1. 所有的應用都是按照位元組流=>字元流=>位元組流方式進行的處理的:
      byte_stream ==[input decoding]==> unicode_char_stream ==[output encoding]==> byte_stream;
    2. 在Java位元組流到字元流(或者反之)都是含有隱含的解碼處理的(預設是按照系統預設編碼方式);
    3. 最早的位元組流解碼過程從javac的程式碼編譯就開始了;
    4. Java中的字元character儲存單位是雙位元組的UNICODE;

    應根據瀏覽器語言設定自動切換字符集

    首先一個概念:即使是基於Java的WEB應用,在和客戶端之間傳遞的仍然是位元組流,比如我從一箇中文客戶端的瀏覽器表單中提交“世界你好”這4箇中文字到伺服器時:首先瀏覽器按照GBK方式編碼成位元組流CA C0 BD E7 C4 E3 BA C3,然後8個位元組按照URLEncoding的規範轉成:%CA%C0%BD%E7%C4%E3%BA%C3,伺服器端的Servlet接收到請求後應該按什麼解碼處理,輸出時又應該按什麼方式編碼行位元組流呢?

    在目前的Servlet的規範中,如果不指定的話透過WEB提交時的輸入ServletRequest和輸出時的ServletResponse預設都是ISO-8859-1方式編/碼解碼的(注意,這裡的編碼/解碼方式是和作業系統環境中的語言環境是無關的)。因此,即使伺服器作業系統的語言環境是中文,上面輸入的請求仍然按英文解碼成8個UNICODE字元,輸出時仍按照英文再編碼成8個位元組,雖然這樣在瀏覽器端如果設定是中文能夠正確顯示,但實際上讀寫的是“位元組”,正確的方式是應該根據客戶端瀏覽器設定ServletRequest和ServletResponse用相應語言的編碼方式進行輸入解碼/輸入編碼,就是這樣一個監測客戶端瀏覽器語言設定的例子:

    當根據瀏覽器的頭資訊中的"Accept-Language"為zh-cn(中文)時,設定請求的解碼方式和輸出的字符集編碼方式使用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

    
    

    再做一個試驗:把程式開頭部分的瀏覽器自動檢測功能註釋掉,再次的輸出結果就是和目前很多應用一樣其實是按ISO-8859-1方式解碼/編碼的“位元組應用”了:

    '世界你好' 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

    雖然這樣的輸出結果如果在瀏覽器中設定用中文字符集也能正確顯示,但實際上處理的已經是“位元組”而不是處理中文“字元”了。ServletRequest 和 ServletResponse 預設使用ISO-8859-1字符集解碼/編碼的具體定義請參考:
    

    以前能夠配置讓一個WEB應用能夠在GBK方式編碼的中文伺服器上和按ISO-8859-1方式編碼的GNU/Linux上都能夠正確的顯示中文一直讓我迷惑了很久。我仔細想了一下,後來終於想明白了,在一個國際化的應用中:ServletRequest和ServletResponse的編碼/解碼方式的確不應該根據伺服器設定成固定的字符集,而應該是面向客戶端語言環境進行輸入/輸出編碼方式的自適應。一個按照國際化規範設計的WEB應用中:

    • 在Servlet的中儘量不要有中文:因為在MVC中,Servlet主要是控制器(C)的角色,因此,應該透過ReBundle機制由Servlet控制轉向到相應的顯示器(或者T)中,所以應該將與本地介面語言相關的介面顯示的部分從Servlet和後臺的模組中完全剝離出來,放到相應的檔案中或者XSLT檔案中。這樣源程式裡完全是英文,編譯時完全不需要考慮字符集的問題。

      如果Servlet實在需要包含中文,則需要設定應用伺服器的Javac編譯選項,加上-encoding選項成系統預設的字符集,如果把用中文編寫的字元按照英文方式解碼編譯,然後再按照英文方式輸出,雖然結果表面正確,實際上都成了面向“位元組”。
    • 在Servlet層,應該像GOOGLE搜擎那樣,設計成能夠根據客戶端瀏覽器的語言環境自適應輸出,為了判斷瀏覽器的語言Servlet中應該有類似以下的程式碼:

      public void doGet (HttpServletRequest req, HttpServletResponse res)
      throws ServletException, IOException {
      //從HTTP請求的頭資訊中獲取客戶端的語言設定
      String clientLanguage = req.getHeader("Accept-Language");

      //簡體中文瀏覽器
      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");
      }
      //預設認為是英文瀏覽器
      else {
      req.setCharacterEncoding("ISO-8859-1");
      res.setContentType("text/html; charset=ISO-8859-1");
      }
      ...
      //設定好request的解碼方式和response的編碼方式後,進行後續的操作。
      //比如再轉向到HelloWorld.gbk.jsp HelloWorld.big5.jsp HelloWorld.jis.jsp等
      }

    而SERVLET預設將字符集設定為ISO-8859-1也許是標準制定者認為英文的瀏覽器佔大多數吧(而且按照ISO-8859-1方式輸出介面往往也是正確的)。

    結論:

    過以上幾個Java試驗程式得出的一些結論:

    • Java環境是基於作業系統上的一個虛擬機器應用,因此,如果作業系統遵循國際化規範:JVM的預設編碼方式可以透過修改作業系統的LOCALE設定實現。對於一個Java應用來說,只要將LINUX的預設編碼方式設定成GBK,其文字編碼處理應該和中文Windows平臺上的表現是一致的。
        6.X使用linux核心的是基於glibc2.1.X,不支援中文LOCALE,因此無法透過改變LOCALE設定改變JVM的預設編碼方式,linux核心2.4開始基於glibc.2.2.x,對中文LOCALE有了比較好的支援。
    • 不同的JVM對字符集的支援程度不同:
        比如:IBM的JVM1.3.0開始支援GB18030,SUN的JVM從1.4開始支援GB18030
    • 正確的編碼方式不一定表示能正確的顯示,正確的顯示還要需要相應的前端顯示系統(字型檔)的支援
        但對於Linux上的服務應用來說,往往只要能確認字元正確的按照指定的方式編碼就夠了
    • 如果應用的是基於UNICODE的編碼方式處理並使用UTF8字符集做集中儲存,這樣最便於根據客戶端語言環境做本地化輸出;

    根據以上結論,設計一個適應多語言環境的應用,可以考慮一下2個應用處理模式:

    • (客戶端應用或本地化應用)根據LOCALE,讓Java應用根據系統LOCALE的預設的字符集設定進行切換,按系統預設的字符集進行編碼解碼,減少應用在編碼處理上的複雜程度。
      輸入位元組流 ==>按系統語言字符集設定將位元組流解碼==> UNICODE處理 ==> 按系統語言字符集設定將UNICODE編碼成位元組流 ==> 輸出位元組流
       
    • (伺服器端或跨語言平臺應用):在應用的最外端:資料輸入輸出判斷語言環境,核心按照UNICODE方式處理儲存。可以把各種區域性的字符集(GB2312 BIG5)看成是UNICODE的一個子集。UNICODE儲存的資料可以方便的轉換成任意字符集。
      應用使用UTF8方式儲存雖然要增加了儲存空間,但也可以大大簡化前端應用本地化(i10n)的複雜程度。 

      簡體中文輸入 繁體中文輸入 簡體中文輸出 繁體中文輸出
      / /
      判斷使用者語言環境:解碼 判斷使用者語言環境:編碼
      /
      中間處理過程:UNICODE
      |
      UTF8編碼儲存

    隨著UNICODE被愈來愈多的系統和平臺支援: Glibc等,但我們應該珍惜一開始就按照國際化規範設計Java,並將其和新發展起來的規範相配合,相信符合國際化規範的應用設計從長遠來看會展現出更多的優勢。

    TODO:
    應用中的字符集問題試驗:My JC

    參考文件:
    Java的國際化設計

    Linux 國際化本地化和中文化

    Linux 程式設計師必讀:中文化與GB18030標準

    Unicode FAQ

    (中文版)

    Java 程式設計技術中漢字問題的分析及解決
    http://www-900.ibm.com/developerWorks/cn/java/java_chinese/index.shtml

    漢字的編碼方式:

    不同版本的JVM支援的編碼方式

    附錄:

     

    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

     

    原文出處:


    來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/10752043/viewspace-992515/,如需轉載,請註明出處,否則將追究法律責任。

    相關文章