- TEL:131 7970 3111
-
慧網(wǎng)微信
- 掃描二維碼
- 關(guān)注邳州在線
-
手機(jī)網(wǎng)站
- 手機(jī)掃描二維碼
- 進(jìn)入手機(jī)站
網(wǎng)站地圖
付款方式
世界上的各地區(qū)都有本地的語言。地區(qū)差異直接導(dǎo)致了語言環(huán)境的差異。在開發(fā)一個(gè)國(guó)際化程序的過程中,處理語言問題顯得很重要了。
這是一個(gè)世界范圍內(nèi)都存在的問題,所以,Java提供了世界性的解決方法。本文描述的方法是用于處理中文的,但是,推而廣之,對(duì)于處理世界上其它國(guó)家和地區(qū)的語言同樣適用。
漢字是雙字節(jié)的。所謂雙字節(jié)是指一個(gè)雙字要占用兩個(gè)BYTE的位置(即16位),分別稱為高位和低位。中國(guó)規(guī)定的漢字編碼為GB2312,這是強(qiáng)制性的,目前幾乎所有的能處理中文的應(yīng)用程序都支持GB2312。GB2312包括了一二級(jí)漢字和9區(qū)符號(hào),高位從0xa1到0xfe,低位也是從0xa1到0xfe,其中,漢字的編碼范圍為0xb0a1到0xf7fe。
另外有一種編碼,叫做GBK,但這是一份規(guī)范,不是強(qiáng)制的。GBK提供了902個(gè)漢字,它兼容GB2312,編碼范圍為0x8140到0xfefe。GBK中的所有字符都可以一一映射到Unicode 2.0。
在不久的將來,中國(guó)會(huì)頒布另一種標(biāo)準(zhǔn):GB18030-00(GBK2K)。它收錄了藏、蒙等少數(shù)民族的字型,從根本上解決了字位不足的問題。注意:它不再是定長(zhǎng)的。其二字節(jié)部份與GBK兼容,四字節(jié)部分是擴(kuò)充的字符、字形。它的首字節(jié)和第三字節(jié)從0x81到0xfe,二字節(jié)和第四字節(jié)從0x30到0x39。
本文不打算介紹Unicode,有興趣的可以瀏覽“http://www.unicode.org/”查看更多的信息。Unicode有一個(gè)特性:它包括了世界上所有的字符字形。所以,各個(gè)地區(qū)的語言都可以建立與Unicode的映射關(guān)系,而Java正是利用了這一點(diǎn)以達(dá)到異種語言之間的轉(zhuǎn)換。
在JDK中,與中文相關(guān)的編碼有:
表1 JDK中與中文相關(guān)的編碼列表
編碼名稱 說明
ASCII 7位,與ascii7相同
ISO8859-1 8-位,與 8859_1,ISO-8859-1,ISO_8859-1,latin1...等相同
GB2312-80 16位,與gb2312,gb2312-1980,EUC_CN,euccn,1381,Cp1381, 1383, Cp1383, ISO22CN,ISO22CN_GB...等相同
GBK 與MS936相同,注意:區(qū)分大小寫
UTF8 與UTF-8相同
GB18030 與cp1392、1392相同,目前支持的JDK很少
在實(shí)際編程時(shí),接觸得比較多的是GB2312(GBK)和ISO8859-1。
為什么會(huì)有“?”號(hào)
上文說過,異種語言之間的轉(zhuǎn)換是通過Unicode來完成的。假設(shè)有兩種不同的語言A和B,轉(zhuǎn)換的步驟為:先把A轉(zhuǎn)化為Unicode,再把Unicode轉(zhuǎn)化為B。
舉例說明。有GB2312中有一個(gè)漢字“李”,其編碼為“C0EE”,欲轉(zhuǎn)化為ISO8859-1編碼。步驟為:先把“李”字轉(zhuǎn)化為Unicode,得到“674E”,再把“674E”轉(zhuǎn)化為ISO8859-1字符。當(dāng)然,這個(gè)映射不會(huì)成功,因?yàn)镮SO8859-1中根本沒有與“674E”對(duì)應(yīng)的字符。
當(dāng)映射不成功時(shí),問題發(fā)生了!當(dāng)從某語言向Unicode轉(zhuǎn)化時(shí),如果在某語言中沒有該字符,得到的將是Unicode的代碼“\uffffd”(“\u”表示是Unicode編碼,)。而從Unicode向某語言轉(zhuǎn)化時(shí),如果某語言沒有對(duì)應(yīng)的字符,則得到的是“0x3f”(“?”)。這是“?”的由來。
例如:把字符流buf =“0x80 0x40 0xb0 0xa1”進(jìn)行new String(buf, "gb2312")操作,得到的結(jié)果是“\ufffd\u554a”,再println出來,得到的結(jié)果將是“?啊”,因?yàn)椤?x80 0x40”是GBK中的字符,在GB2312中沒有。
再如,把字符串String="\u00d6\u00ec\u00e9\u0046\u00bb\u00f9"進(jìn)行new String (buf.getBytes("GBK"))操作,得到的結(jié)果是“3fa8aca8a6463fa8b4”,其中,“\u00d6”在“GBK”中沒有對(duì)應(yīng)的字符,得到“3f”,“\u00ec”對(duì)應(yīng)著“a8ac”,“\u00e9”對(duì)應(yīng)著“a8a6”,“0046”對(duì)應(yīng)著“46”(因?yàn)檫@是ASCII字符),“\u00bb”沒找到,得到“3f”,,“\u00f9”對(duì)應(yīng)著“a8b4”。把這個(gè)字符串println一下,得到的結(jié)果是“?ìéF?ù”?吹?jīng)]?這里并不全是問號(hào),因?yàn)镚BK與Unicode映射的內(nèi)容中除了漢字外還有字符,本例是的明證。
所以,在漢字轉(zhuǎn)碼時(shí),如果發(fā)生錯(cuò)亂,得到的不一定都是問號(hào)噢!不過,錯(cuò)了終究是錯(cuò)了,50步和100步并沒有質(zhì)的差別。
或者會(huì)問:如果源字符集中有,而Unicode中沒有,結(jié)果會(huì)如何?回答是不知道。因?yàn)槲沂诸^沒有能做這個(gè)測(cè)試的源字符集。但有一點(diǎn)是肯定的,那是源字符集不夠規(guī)范。在Java中,如果發(fā)生這種情況,是會(huì)拋出異常的。