網上就JSP/Servlet中DBCS字元編碼問題有許多優秀的文章和討論,本文對它們作一些整理,並結合IBM WebSphere Application Server 3.5(WAS)的解決方案作一些說明,希望它不是多餘的。
內容:
問題的起源
GB2312-80,GBK,GB18030-2000 漢字字元集及 Encoding
中文轉碼時´?´、亂碼的由來
JSP/Servlet 漢字編碼問題及在 WAS中的解決辦法
結束語
參考文章
1.問題的起源
每個國家(或地區)都規定了電腦資訊交換用的字元編碼集,如美國的擴充 ASCII碼,中國的GB2312-80,日本的JIS 等,作為該國家/地區內資訊處理的基礎,有著統一編碼的重要作用。字元編碼集按長度分為 SBCS(單一位元組字元集),DBCS(雙位元組字元集)兩大類。早期的軟體(尤其是作業系統),為瞭解決本地字元資訊的電腦處理,出現了各種語言版本(L10N),為了區分,引進了LANG, Codepage 等概念。但是由於各個本地字元集代碼範圍重疊,相互間資訊交換困難;軟體各個語言版本獨立維護成本較高。因此有必要將本地化工作中的共性抽取出來,作一致處理,將特別的本地化處理內容降低到最少。這也就是所謂的國際化(I18N)。各種語言資訊被進一步規範為 Locale 資訊。處理的底層字元集變成了幾乎包含了所有字形的Unicode。
現在大部分具有國際化特徵的軟體核心字元處理都是以 Unicode 為基礎的,在軟體運行時根據當時的Locale/Lang/Codepage 設定確定相應的本地字元編碼設定,並依此處理本地字元。在處理過程中需要實現 Unicode 和本地字元集的相互轉換,甚或以 Unicode 為中間的兩個不同本地字元集的相互轉換。這種方式在網路環境下被進一步延伸,任何網路兩端的字元資訊也需要根據字元集的設定轉換成可接受的內容。
Java 語言內部是用 Unicode 表示字元的,遵守 Unicode V2.0。Java 程式無論是從/往檔案系統以字元流讀/寫檔案,還是往 URL 串連寫 HTML 資訊,或從 URL 串連讀取參數值,都會有字元編碼的轉換。這樣做雖然增加了編程的複雜度,容易引起混淆,但卻是符合國際化的思想的。
從理論上來說,這些根據字元集設定而進行的字元轉換不應該產生太多問題。而事實是由於應用程式的實際運行環境不同,Unicode 和各個本地字元集的補充、完善,以及系統或應用程式實現的不規範,轉碼時出現的問題時時困擾著程式員和使用者。
2. GB2312-80,GBK,GB18030-2000 漢字字元集及 Encoding
其實解決 JAVA 程式中的漢字編碼問題的方法往往很簡單,但理解其背後的原因,定位問題,還需要瞭解現有的漢字編碼和編碼轉換。
GB2312-80 是在國內電腦漢字資訊技術發展初始階段制定的,其中包含了大部分常用的一、二級漢字,和 9 區的符號。該字元集是幾乎所有的中文系統和國際化的軟體都支援的中文字元集,這也是最基本的中文字元集。其編碼範圍是高位0xa1-0xfe,低位也是 0xa1-0xfe;漢字從 0xb0a1 開始,結束於 0xf7fe;
GBK 是 GB2312-80的擴充,是向上相容的。它包含了20902 個漢字,其編碼範圍是 0x8140-0xfefe,剔除高位 0x80的字位。其所有字元都可以一對一映射到 Unicode 2.0,也就是說 JAVA 實際上提供了GBK 字元集的支援。這是現階段 Windows 和其它一些中文作業系統的預設字元集,但並不是所有的國際化軟體都支援該字元集,感覺是他們並不完全知道 GBK 是怎麼回事。值得注意的是它不是國家標準,而只是規範。隨著 GB18030-2000國標的發布,它將在不久的將來完成它的曆史使命。
GB18030-2000(GBK2K) 在 GBK的基礎上進一步擴充了漢字,增加了藏、蒙等少數民族的字形。GBK2K 從根本上解決了字位不夠,字形不足的問題。它有幾個特點,它並沒有確定所有的字形,只是規定了編碼範圍,留待以後擴充。
編碼是變長的,其二位元組部分與 GBK 相容;四位元組部分是擴充的字形、字位,其編碼範圍是首位元組 0x81-0xfe、二位元組0x30-0x39、三位元組 0x81-0xfe、四位元組0x30-0x39。
它的推廣是分階段的,首先要求實現的是能夠完全映射到 Unicode 3.0 標準的所有字形。
它是國家標準,是強制性的。
現在還沒有任何一個作業系統或軟體實現了GBK2K的支援,這是現階段和將來漢化的工作內容。
Unicode的介紹......就免了吧。
JAVA支援的encoding中與中文編程相關的有:(有幾個在JDK文檔中未列出)
ASCII 7-bit, 同 ascii7
ISO8859-1 8-bit, 同 8859_1,ISO-8859-1,ISO_8859-1,latin1...
GB2312-80 同gb2312,gb2312-1980,EUC_CN,euccn,1381,Cp1381, 1383, Cp1383, ISO2022CN,ISO2022CN_GB......
GBK (注意大小寫),同MS936
UTF8 UTF-8
GB18030 (現在只有IBM JDK1.3.?有支援), 同Cp1392,1392
JAVA 語言採用Unicode處理字元. 但從另一個角度來說,在java程式中也可以採用非Unicode的轉碼,重要的是保證程式入口和出口的漢字資訊不失真。如完全採用ISO-8859-1來處理漢字也能達到正確的結果。網路上流行的許多解決方案,都屬於這種類型。為了不致引起混淆,本文不對這種方法作討論。