色尼玛亚洲综合影院,亚洲3atv精品一区二区三区,麻豆freexxxx性91精品,欧美在线91

深入剖析JSP和Servlet對中文的處理

  世界上的各地區(qū)都有本地的語言。地區(qū)差異直接導(dǎo)致了語言環(huán)境的差異。在開發(fā)一個國際化程序的過程中,處理語言問題就顯得很重要了。

  這是一個世界范圍內(nèi)都存在的問題,所以,Java提供了世界性的解決方法。本文描述的方法是用于處理中文的,但是,推而廣之,對于處理世界上其它國家和地區(qū)的語言同樣適用。

  漢字是雙字節(jié)的。所謂雙字節(jié)是指一個雙字要占用兩個BYTE的位置(即16位),分別稱為高位和低位。中國規(guī)定的漢字編碼為GB2312,這是強(qiáng)制性的,目前幾乎所有的能處理中文的應(yīng)用程序都支持GB2312。GB2312包括了一二級漢字和9區(qū)符號,高位從0xa1到0xfe,低位也是從0xa1到0xfe,其中,漢字的編碼范圍為0xb0a1到0xf7fe。

  另外有一種編碼,叫做GBK,但這是一份規(guī)范,不是強(qiáng)制的。GBK提供了20902個漢字,它兼容GB2312,編碼范圍為0x8140到0xfefe。GBK中的所有字符都可以一一映射到Unicode 2.0。

  在不久的將來,中國會頒布另一種標(biāo)準(zhǔn):GB18030-2000(GBK2K)。它收錄了藏、蒙等少數(shù)民族的字型,從根本上解決了字位不足的問題。注意:它不再是定長的。其二字節(jié)部份與GBK兼容,四字節(jié)部分是擴(kuò)充的字符、字形。它的首字節(jié)和第三字節(jié)從0x81到0xfe,二字節(jié)和第四字節(jié)從0x30到0x39。

  本文不打算介紹Unicode,有興趣的可以瀏覽“http://www.unicode.org/”查看更多的信息。Unicode有一個特性:它包括了世界上所有的字符字形。所以,各個地區(qū)的語言都可以建立與Unicode的映射關(guān)系,而Java正是利用了這一點(diǎn)以達(dá)到異種語言之間的轉(zhuǎn)換。

  在JDK中,與中文相關(guān)的編碼有:

  表1 JDK中與中文相關(guān)的編碼列表

編碼名稱說明
ASCII7位,與ascii7相同
ISO8859-18-位,與 8859_1,ISO-8859-1,ISO_8859-1,latin1...等相同
GB2312-8016位,與gb2312,gb2312-1980,EUC_CN,euccn,1381,Cp1381, 1383, Cp1383, ISO2022CN,ISO2022CN_GB...等相同
GBK與MS936相同,注意:區(qū)分大小寫
UTF8與UTF-8相同
GB18030與cp1392、1392相同,目前支持的JDK很少

  在實(shí)際編程時,接觸得比較多的是GB2312(GBK)和ISO8859-1。

  為什么會有“?”號

  上文說過,異種語言之間的轉(zhuǎn)換是通過Unicode來完成的。假設(shè)有兩種不同的語言A和B,轉(zhuǎn)換的步驟為:先把A轉(zhuǎn)化為Unicode,再把Unicode轉(zhuǎn)化為B。

  舉例說明。有GB2312中有一個漢字“李”,其編碼為“C0EE”,欲轉(zhuǎn)化為ISO8859-1編碼。步驟為:先把“李”字轉(zhuǎn)化為Unicode,得到“674E”,再把“674E”轉(zhuǎn)化為ISO8859-1字符。當(dāng)然,這個映射不會成功,因?yàn)镮SO8859-1中根本就沒有與“674E”對應(yīng)的字符。

  當(dāng)映射不成功時,問題就發(fā)生了!當(dāng)從某語言向Unicode轉(zhuǎn)化時,如果在某語言中沒有該字符,得到的將是Unicode的代碼“/uffffd”(“/u”表示是Unicode編碼,)。而從Unicode向某語言轉(zhuǎn)化時,如果某語言沒有對應(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”中沒有對應(yīng)的字符,得到“3f”,“/u00ec”對應(yīng)著“a8ac”,“/u00e9”對應(yīng)著“a8a6”,“0046”對應(yīng)著“46”(因?yàn)檫@是ASCII字符),“/u00bb”沒找到,得到“3f”,最后,“/u00f9”對應(yīng)著“a8b4”。把這個字符串println一下,得到的結(jié)果是“?ìéF?ù”。看到?jīng)]?這里并不全是問號,因?yàn)镚BK與Unicode映射的內(nèi)容中除了漢字外還有字符,本例就是最好的明證。

  所以,在漢字轉(zhuǎn)碼時,如果發(fā)生錯亂,得到的不一定都是問號噢!不過,錯了終究是錯了,50步和100步并沒有質(zhì)的差別。

  或者會問:如果源字符集中有,而Unicode中沒有,結(jié)果會如何?回答是不知道。因?yàn)槲沂诸^沒有能做這個測試的源字符集。但有一點(diǎn)是肯定的,那就是源字符集不夠規(guī)范。在Java中,如果發(fā)生這種情況,是會拋出異常的。

  什么是UTF

  UTF,是Unicode Text Format的縮寫,意為Unicode文本格式。對于UTF,是這樣定義的:

  (1)如果Unicode的16位字符的頭9位是0,則用一個字節(jié)表示,這個字節(jié)的首位是“0”,剩下的7位與原字符中的后7位相同,如“/u0034”(0000 0000 0011 0100),用“34” (0011 0100)表示;(與源Unicode字符是相同的);

  (2)如果Unicode的16位字符的頭5位是0,則用2個字節(jié)表示,首字節(jié)是“110”開頭,后面的5位與源字符中除去頭5個零后的最高5位相同;第二個字節(jié)以“10”開頭,后面的6位與源字符中的低6位相同。如“/u025d”(0000 0010 0101 1101),轉(zhuǎn)化后為“c99d”(1100 1001 1001 1101);

  (3)如果不符合上述兩個規(guī)則,則用三個字節(jié)表示。第一個字節(jié)以“1110”開頭,后四位為源字符的高四位;第二個字節(jié)以“10”開頭,后六位為源字符中間的六位;第三個字節(jié)以“10”開頭,后六位為源字符的低六位;如“/u9da7”(1001 1101 1010 0111),轉(zhuǎn)化為“e9b6a7”(1110 1001 1011 0110 1010 0111);

  可以這么描述Java程序中Unicode與UTF的關(guān)系,雖然不絕對:字符串在內(nèi)存中運(yùn)行時,表現(xiàn)為Unicode代碼,而當(dāng)要保存到文件或其它介質(zhì)中去時,用的是UTF。這個轉(zhuǎn)化過程是由writeUTF和readUTF來完成的。

  好了,基礎(chǔ)性的論述差不多了,下面進(jìn)入正題。

  先把這個問題想成是一個黑匣子。先看黑匣子的一級表示:

input(charsetA)->process(Unicode)->output(charsetB)

  簡單,這就是一個IPO模型,即輸入、處理和輸出。同樣的內(nèi)容要經(jīng)過“從charsetA到unicode再到charsetB”的轉(zhuǎn)化。

  再看二級表示:

SourceFile(jsp,Java)->class->output

  在這個圖中,可以看出,輸入的是jsp和Java源文件,在處理過程中,以Class文件為載體,然后輸出。再細(xì)化到三級表示:

jsp->temp file->class->browser,os console,db

app,servlet->class->browser,os console,db

  這個圖就更明白了。Jsp文件先生成中間的Java文件,再生成Class。而Servlet和普通App則直接編譯生成Class。然后,從Class再輸出到瀏覽器、控制臺或數(shù)據(jù)庫等。

  JSP:從源文件到Class的過程

  Jsp的源文件是以“.jsp”結(jié)尾的文本文件。在本節(jié)中,將闡述JSP文件的解釋和編譯過程,并跟蹤其中的中文變化。

  1、JSP/Servlet引擎提供的JSP轉(zhuǎn)換工具(jspc)搜索JSP文件中用<%@ page contentType ="text/html; charset=<Jsp-charset>"%>中指定的charset。如果在JSP文件中未指定<Jsp-charset>,則取JVM中的默認(rèn)設(shè)置file.encoding,一般情況下,這個值是ISO8859-1;

  2、jspc用相當(dāng)于“Javac

主站蜘蛛池模板: 哈密市| 宁海县| 洪湖市| 南皮县| 开原市| 海口市| 沧州市| 建始县| 吉安县| 新宁县| 敦化市| 郴州市| 克拉玛依市| 南和县| 文水县| 达州市| 昆明市| 天水市| 滨州市| 介休市| 神农架林区| 育儿| 滨海县| 思南县| 伊吾县| 宝鸡市| 屏东县| 山东| 深水埗区| 洛扎县| 甘洛县| 庆安县| 永年县| 峨眉山市| 大埔县| 云南省| 玉龙| 闽清县| 延边| 东乌珠穆沁旗| 西昌市|