深入剖析关于JSP和Servlet对中文的处理世界上的各地区都有本地的语言。地区差异直接导致了语言环境的差异。在开发一个国际化程序的过程中,处理语言问题就显得很重要了。
深入剖析关于JSP和Servlet对中文的处理
深入剖析关于JSP和Servlet对中文的处理  这是一个世界范围内都存在的问题,所以,Java提供了世界性的解决方法。本文描述的方法是用于处理中文的,但是,推而广之,对于处理世界上其它国家和地区的语言同样适用。
深入剖析关于JSP和Servlet对中文的处理
深入剖析关于JSP和Servlet对中文的处理  汉字是双字节的。所谓双字节是指一个双字要占用两个BYTE的位置(即16位),分别称为高位和低位。中国规定的汉字编码为GB2312,这是强制性的,目前几乎所有的能处理中文的应用程序都支持GB2312。GB2312包括了一二级汉字和9区符号,高位从0xa1到0xfe,低位也是从0xa1到0xfe,其中,汉字的编码范围为0xb0a1到0xf7fe。
深入剖析关于JSP和Servlet对中文的处理
深入剖析关于JSP和Servlet对中文的处理  另外有一种编码,叫做GBK,但这是一份规范,不是强制的。GBK提供了20902个汉字,它兼容GB2312,编码范围为0x8140到0xfefe。GBK中的所有字符都可以一一映射到Unicode 2.0。
深入剖析关于JSP和Servlet对中文的处理
深入剖析关于JSP和Servlet对中文的处理  在不久的将来,中国会颁布另一种标准:GB18030-2000(GBK2K)。它收录了藏、蒙等少数民族的字型,从根本上解决了字位不足的问题。注意:它不再是定长的。其二字节部份与GBK兼容,四字节部分是扩充的字符、字形。它的首字节和第三字节从0x81到0xfe,二字节和第四字节从0x30到0x39。
深入剖析关于JSP和Servlet对中文的处理
深入剖析关于JSP和Servlet对中文的处理  本文不打算介绍Unicode,有兴趣的可以浏览“http://www.unicode.org/”查看更多的信息。Unicode有一个特性:它包括了世界上所有的字符字形。所以,各个地区的语言都可以建立与Unicode的映射关系,而Java正是利用了这一点以达到异种语言之间的转换。
深入剖析关于JSP和Servlet对中文的处理
深入剖析关于JSP和Servlet对中文的处理  在JDK中,与中文相关的编码有:
深入剖析关于JSP和Servlet对中文的处理
深入剖析关于JSP和Servlet对中文的处理  表1 JDK中与中文相关的编码列表
深入剖析关于JSP和Servlet对中文的处理
深入剖析关于JSP和Servlet对中文的处理编码名称 说明 
深入剖析关于JSP和Servlet对中文的处理ASCII 7位,与ascii7相同 
深入剖析关于JSP和Servlet对中文的处理ISO8859-1 8-位,与 8859_1,ISO-8859-1,ISO_8859-1,latin1深入剖析关于JSP和Servlet对中文的处理等相同 
深入剖析关于JSP和Servlet对中文的处理GB2312-80 16位,与gb2312,gb2312-1980,EUC_CN,euccn,1381,Cp1381, 1383, Cp1383, ISO2022CN,ISO2022CN_GB深入剖析关于JSP和Servlet对中文的处理等相同 
深入剖析关于JSP和Servlet对中文的处理GBK 与MS936相同,注意:区分大小写 
深入剖析关于JSP和Servlet对中文的处理UTF8 与UTF-8相同 
深入剖析关于JSP和Servlet对中文的处理GB18030 与cp1392、1392相同,目前支持的JDK很少 
深入剖析关于JSP和Servlet对中文的处理
深入剖析关于JSP和Servlet对中文的处理  在实际编程时,接触得比较多的是GB2312(GBK)和ISO8859-1。
深入剖析关于JSP和Servlet对中文的处理
深入剖析关于JSP和Servlet对中文的处理  为什么会有“?”号
深入剖析关于JSP和Servlet对中文的处理
深入剖析关于JSP和Servlet对中文的处理  上文说过,异种语言之间的转换是通过Unicode来完成的。假设有两种不同的语言A和B,转换的步骤为:先把A转化为Unicode,再把Unicode转化为B。
深入剖析关于JSP和Servlet对中文的处理
深入剖析关于JSP和Servlet对中文的处理  举例说明。有GB2312中有一个汉字“李”,其编码为“C0EE”,欲转化为ISO8859-1编码。步骤为:先把“李”字转化为Unicode,得到“674E”,再把“674E”转化为ISO8859-1字符。当然,这个映射不会成功,因为ISO8859-1中根本就没有与“674E”对应的字符。
深入剖析关于JSP和Servlet对中文的处理
深入剖析关于JSP和Servlet对中文的处理  当映射不成功时,问题就发生了!当从某语言向Unicode转化时,如果在某语言中没有该字符,得到的将是Unicode的代码“\uffffd”(“\u”表示是Unicode编码,)。而从Unicode向某语言转化时,如果某语言没有对应的字符,则得到的是“0x3f”(“?”)。这就是“?”的由来。
深入剖析关于JSP和Servlet对中文的处理
深入剖析关于JSP和Servlet对中文的处理  例如:把字符流buf =“0x80 0x40 0xb0 0xa1”进行new String(buf, "gb2312")操作,得到的结果是“\ufffd\u554a”,再println出来,得到的结果将是“?啊”,因为“0x80 0x40”是GBK中的字符,在GB2312中没有。
深入剖析关于JSP和Servlet对中文的处理
深入剖析关于JSP和Servlet对中文的处理  再如,把字符串String="\u00d6\u00ec\u00e9\u0046\u00bb\u00f9"进行new String (buf.getBytes("GBK"))操作,得到的结果是“3fa8aca8a6463fa8b4”,其中,“\u00d6”在“GBK”中没有对应的字符,得到“3f”,“\u00ec”对应着“a8ac”,“\u00e9”对应着“a8a6”,“0046”对应着“46”(因为这是ASCII字符),“\u00bb”没找到,得到“3f”,最后,“\u00f9”对应着“a8b4”。把这个字符串println一下,得到的结果是“?ìéF?ù”。看到没?这里并不全是问号,因为GBK与Unicode映射的内容中除了汉字外还有字符,本例就是最好的明证。
深入剖析关于JSP和Servlet对中文的处理
深入剖析关于JSP和Servlet对中文的处理  所以,在汉字转码时,如果发生错乱,得到的不一定都是问号噢!不过,错了终究是错了,50步和100步并没有质的差别。
深入剖析关于JSP和Servlet对中文的处理
深入剖析关于JSP和Servlet对中文的处理  或者会问:如果源字符集中有,而Unicode中没有,结果会如何?回答是不知道。因为我手头没有能做这个测试的源字符集。但有一点是肯定的,那就是源字符集不够规范。在Java中,如果发生这种情况,是会抛出异常的。
深入剖析关于JSP和Servlet对中文的处理
深入剖析关于JSP和Servlet对中文的处理
深入剖析关于JSP和Servlet对中文的处理wwww.chin aitpower.comA8GS7iZj14UFuEmHNTTIELclR
深入剖析关于JSP和Servlet对中文的处理  什么是UTF
深入剖析关于JSP和Servlet对中文的处理
深入剖析关于JSP和Servlet对中文的处理  UTF,是Unicode Text Format的缩写,意为Unicode文本格式。对于UTF,是这样定义的:
深入剖析关于JSP和Servlet对中文的处理
深入剖析关于JSP和Servlet对中文的处理  (1)如果Unicode的16位字符的头9位是0,则用一个字节表示,这个字节的首位是“0”,剩下的7位与原字符中的后7位相同,如“\u0034”(0000 0000 0011 0100),用“34” (0011 0100)表示;(与源Unicode字符是相同的);
深入剖析关于JSP和Servlet对中文的处理
深入剖析关于JSP和Servlet对中文的处理  (2)如果Unicode的16位字符的头5位是0,则用2个字节表示,首字节是“110”开头,后面的5位与源字符中除去头5个零后的最高5位相同;第二个字节以“10”开头,后面的6位与源字符中的低6位相同。如“\u025d”(0000 0010 0101 1101),转化后为“c99d”(1100 1001 1001 1101);
深入剖析关于JSP和Servlet对中文的处理
深入剖析关于JSP和Servlet对中文的处理  (3)如果不符合上述两个规则,则用三个字节表示。第一个字节以“1110”开头,后四位为源字符的高四位;第二个字节以“10”开头,后六位为源字符中间的六位;第三个字节以“10”开头,后六位为源字符的低六位;如“\u9da7”(1001 1101 1010 0111),转化为“e9b6a7”(1110 1001 1011 0110 1010 0111);
深入剖析关于JSP和Servlet对中文的处理
深入剖析关于JSP和Servlet对中文的处理  可以这么描述JAVA程序中Unicode与UTF的关系,虽然不绝对:字符串在内存中运行时,表现为Unicode代码,而当要保存到文件或其它介质中去时,用的是UTF。这个转化过程是由writeUTF和readUTF来完成的。
深入剖析关于JSP和Servlet对中文的处理
深入剖析关于JSP和Servlet对中文的处理  好了,基础性的论述差不多了,下面进入正题。
深入剖析关于JSP和Servlet对中文的处理
深入剖析关于JSP和Servlet对中文的处理  先把这个问题想成是一个黑匣子。先看黑匣子的一级表示:
深入剖析关于JSP和Servlet对中文的处理
深入剖析关于JSP和Servlet对中文的处理input(charsetA)->process(Unicode)->output(charsetB)
深入剖析关于JSP和Servlet对中文的处理
深入剖析关于JSP和Servlet对中文的处理  简单,这就是一个IPO模型,即输入、处理和输出。同样的内容要经过“从charsetA到unicode再到charsetB”的转化。
深入剖析关于JSP和Servlet对中文的处理
深入剖析关于JSP和Servlet对中文的处理  再看二级表示:
深入剖析关于JSP和Servlet对中文的处理
深入剖析关于JSP和Servlet对中文的处理SourceFile(jsp,java)->class->output
深入剖析关于JSP和Servlet对中文的处理
深入剖析关于JSP和Servlet对中文的处理  在这个图中,可以看出,输入的是jsp和java源文件,在处理过程中,以Class文件为载体,然后输出。再细化到三级表示:
深入剖析关于JSP和Servlet对中文的处理
深入剖析关于JSP和Servlet对中文的处理jsp->temp file->class->browser,os console,db
深入剖析关于JSP和Servlet对中文的处理
深入剖析关于JSP和Servlet对中文的处理app,servlet->class->browser,os console,db
深入剖析关于JSP和Servlet对中文的处理
深入剖析关于JSP和Servlet对中文的处理  这个图就更明白了。Jsp文件先生成中间的Java文件,再生成Class。而Servlet和普通App则直接编译生成Class。然后,从Class再输出到浏览器、控制台或数据库等。
深入剖析关于JSP和Servlet对中文的处理
深入剖析关于JSP和Servlet对中文的处理  JSP:从源文件到Class的过程
深入剖析关于JSP和Servlet对中文的处理
深入剖析关于JSP和Servlet对中文的处理  Jsp的源文件是以“.jsp”结尾的文本文件。在本节中,将阐述JSP文件的解释和编译过程,并跟踪其中的中文变化。
深入剖析关于JSP和Servlet对中文的处理
深入剖析关于JSP和Servlet对中文的处理  1、JSP/Servlet引擎提供的JSP转换工具(jspc)搜索JSP文件中用<%@ page contentType ="text/html; charset=<Jsp-charset>"%>中指定的charset。如果在JSP文件中未指定<Jsp-charset>,则取JVM中的默认设置file.encoding,一般情况下,这个值是ISO8859-1;
深入剖析关于JSP和Servlet对中文的处理
深入剖析关于JSP和Servlet对中文的处理  2、jspc用相当于“javac ?encoding <Jsp-charset>”的命令解释JSP文件中出现的所有字符,包括中文字符和ASCII字符,然后把这些字符转换成Unicode字符,再转化成UTF格式,存为JAVA文件。ASCII码字符转化为Unicode字符时只是简单地在前面加“00”,如“A”,转化为“\u0041”(不需要理由,Unicode的码表就是这么编的)。然后,经过到UTF的转换,又变回“41”了!这也就是可以使用普通文本编辑器查看由JSP生成的JAVA文件的原因;
深入剖析关于JSP和Servlet对中文的处理
深入剖析关于JSP和Servlet对中文的处理  3、引擎用相当于“javac ?encoding UNICODE”的命令,把JAVA文件编译成CLASS文件;
深入剖析关于JSP和Servlet对中文的处理
深入剖析关于JSP和Servlet对中文的处理  先看一下这些过程中中文字符的转换情况。有如下源代码:
深入剖析关于JSP和Servlet对中文的处理
深入剖析关于JSP和Servlet对中文的处理<%@ page contentType="text/html; charset=gb2312"%>
深入剖析关于JSP和Servlet对中文的处理<html><body>
深入剖析关于JSP和Servlet对中文的处理<%
深入剖析关于JSP和Servlet对中文的处理 String a="中文";
深入剖析关于JSP和Servlet对中文的处理 out.println(a);
深入剖析关于JSP和Servlet对中文的处理%>
深入剖析关于JSP和Servlet对中文的处理</body></html> 
深入剖析关于JSP和Servlet对中文的处理
深入剖析关于JSP和Servlet对中文的处理  这段代码是在UltraEdit for Windows上编写的。保存后,“中文”两个字的16进制编码为“D6 D0 CE C4”(GB2312编码)。经查表,“中文”两字的Unicode编码为“\u4E2D\u6587”,用 UTF表示就是“E4 B8 AD E6 96 87”。打开引擎生成的由JSP文件转变而成的JAVA文件,发现其中的“中文”两个字确实被“E4 B8 AD E6 96 87”替代了,再查看由JAVA文件编译生成的CLASS文件,发现结果与JAVA文件中的完全一样。
深入剖析关于JSP和Servlet对中文的处理
深入剖析关于JSP和Servlet对中文的处理  再看JSP中指定的CharSet为ISO-8859-1的情况。
深入剖析关于JSP和Servlet对中文的处理
深入剖析关于JSP和Servlet对中文的处理<%@ page contentType="text/html; charset=ISO-8859-1"%>
深入剖析关于JSP和Servlet对中文的处理<html><body>
深入剖析关于JSP和Servlet对中文的处理<%
深入剖析关于JSP和Servlet对中文的处理 String a="中文";
深入剖析关于JSP和Servlet对中文的处理 out.println(a);
深入剖析关于JSP和Servlet对中文的处理%>
深入剖析关于JSP和Servlet对中文的处理</body></html> 
深入剖析关于JSP和Servlet对中文的处理
深入剖析关于JSP和Servlet对中文的处理  同样,该文件是用UltraEdit编写的,“中文”这两个字也是存为GB2312编码“D6 D0 CE C4”。先模拟一下生成的JAVA文件和CLASS文件的过程:jspc用ISO-8859-1来解释“中文”,并把它映射到Unicode。由于ISO-8859-1是8位的,且是拉丁语系,其映射规则就是在每个字节前加“00”,所以,映射后的Unicode编码应为“\u00D6\u00D0\u00CE\u00C4”,转化成UTF后应该是“C3 96 C3 90 C3 8E C3 84”。好,打开文件看一下,JAVA文件和CLASS文件中,“中文”果然都表示为“C3 96 C3 90 C3 8E C3 84”。
深入剖析关于JSP和Servlet对中文的处理
深入剖析关于JSP和Servlet对中文的处理  如果上述代码中不指定<Jsp-charset>,即把第一行写成“<%@ page contentType="text/html" %>”,JSPC会使用file.encoding的设置来解释JSP文件。在RedHat 6.2上,其处理结果与指定为ISO-8859-1是完全相同的。
深入剖析关于JSP和Servlet对中文的处理
深入剖析关于JSP和Servlet对中文的处理  到现在为止,已经解释了从JSP文件到CLASS文件的转变过程中中文字符的映射过程。一句话:从“JspCharSet到Unicode再到UTF”。下表总结了这个过程:
深入剖析关于JSP和Servlet对中文的处理
深入剖析关于JSP和Servlet对中文的处理  表2 “中文”从JSP到CLASS的转化过程
深入剖析关于JSP和Servlet对中文的处理
深入剖析关于JSP和Servlet对中文的处理Jsp-CharSet JSP文件中 JAVA文件中 CLASS文件中 
深入剖析关于JSP和Servlet对中文的处理GB2312 D6 D0 CE C4(GB2312) 从\u4E2D\u6587(Unicode)到E4 B8 AD E6 96 87 (UTF) E4 B8 AD E6 96 87 (UTF) 
深入剖析关于JSP和Servlet对中文的处理ISO-8859-1 D6 D0 CE C4
深入剖析关于JSP和Servlet对中文的处理(GB2312) 从\u00D6\u00D0\u00CE\u00C4 (Unicode)到C3 96 C3 90 C3 8E C3 84 (UTF) C3 96 C3 90 C3 8E C3 84 (UTF) 
深入剖析关于JSP和Servlet对中文的处理无(默认=file.encoding) 同ISO-8859-1 同ISO-8859-1 同ISO-8859-1 
深入剖析关于JSP和Servlet对中文的处理
深入剖析关于JSP和Servlet对中文的处理  下节先讨论Servlet从JAVA文件到CLASS文件的转化过程,然后再解释从CLASS文件如何输出到客户端。之所以这样安排,是因为JSP和Servlet在输出时处理方法是一样的。
深入剖析关于JSP和Servlet对中文的处理
深入剖析关于JSP和Servlet对中文的处理
深入剖析关于JSP和Servlet对中文的处理  Servlet:从源文件到Class的过程
深入剖析关于JSP和Servlet对中文的处理
深入剖析关于JSP和Servlet对中文的处理  Servlet源文件是以“.java”结尾的文本文件。本节将讨论Servlet的编译过程并跟踪其中的中文变化。
深入剖析关于JSP和Servlet对中文的处理
深入剖析关于JSP和Servlet对中文的处理  用“javac”编译Servlet源文件。javac可以带“-encoding <Compile-charset>”参数,意思是“用< Compile-charset >中指定的编码来解释Serlvet源文件”。
深入剖析关于JSP和Servlet对中文的处理
深入剖析关于JSP和Servlet对中文的处理  源文件在编译时,用<Compile-charset>来解释所有字符,包括中文字符和ASCII字符。然后把字符常量转变成Unicode字符,最后,把Unicode转变成UTF。
深入剖析关于JSP和Servlet对中文的处理
深入剖析关于JSP和Servlet对中文的处理  在Servlet中,还有一个地方设置输出流的CharSet。通常在输出结果前,调用HttpServletResponse的setContentType方法来达到与在JSP中设置<Jsp-charset>一样的效果,称之为<Servlet-charset>。
深入剖析关于JSP和Servlet对中文的处理
深入剖析关于JSP和Servlet对中文的处理  注意,文中一共提到了三个变量:<Jsp-charset>、<Compile-charset>和<Servlet-charset>。其中,JSP文件只与<Jsp-charset>有关,而<Compile-charset>和<Servlet-charset>只与Servlet有关。
深入剖析关于JSP和Servlet对中文的处理
深入剖析关于JSP和Servlet对中文的处理  看下例:
深入剖析关于JSP和Servlet对中文的处理
深入剖析关于JSP和Servlet对中文的处理import javax.servlet.*;
深入剖析关于JSP和Servlet对中文的处理
深入剖析关于JSP和Servlet对中文的处理import javax.servlet.http.*;
深入剖析关于JSP和Servlet对中文的处理
深入剖析关于JSP和Servlet对中文的处理class testServlet extends HttpServlet
深入剖析关于JSP和Servlet对中文的处理{
深入剖析关于JSP和Servlet对中文的处理 public void doGet(HttpServletRequest req,HttpServletResponse resp)
深入剖析关于JSP和Servlet对中文的处理 throws ServletException,java.io.IOException
深入剖析关于JSP和Servlet对中文的处理 {
深入剖析关于JSP和Servlet对中文的处理  resp.setContentType("text/html; charset=GB2312");
深入剖析关于JSP和Servlet对中文的处理  java.io.PrintWriter out=resp.getWriter();
深入剖析关于JSP和Servlet对中文的处理  out.println("<html>");
深入剖析关于JSP和Servlet对中文的处理  out.println("#中文#");
深入剖析关于JSP和Servlet对中文的处理  out.println("</html>");
深入剖析关于JSP和Servlet对中文的处理 }
深入剖析关于JSP和Servlet对中文的处理
深入剖析关于JSP和Servlet对中文的处理
深入剖析关于JSP和Servlet对中文的处理  该文件也是用UltraEdit for Windows编写的,其中的“中文”两个字保存为“D6 D0 CE C4”(GB2312编码)。
深入剖析关于JSP和Servlet对中文的处理
深入剖析关于JSP和Servlet对中文的处理  开始编译。下表是<Compile-charset>不同时,CLASS文件中“中文”两字的十六进制码。在编译过程中,<Servlet-charset>不起任何作用。<Servlet-charset>只对CLASS文件的输出产生影响,实际上是<Servlet-charset>和<Compile-charset>一起,达到与JSP文件中的<Jsp-charset>相同的效果,因为<Jsp-charset>对编译和CLASS文件的输出都会产生影响。
深入剖析关于JSP和Servlet对中文的处理
深入剖析关于JSP和Servlet对中文的处理  表3 “中文”从Servlet源文件到Class的转变过程
深入剖析关于JSP和Servlet对中文的处理
深入剖析关于JSP和Servlet对中文的处理Compile-charset Servlet源文件中 Class文件中 等效的Unicode码 
深入剖析关于JSP和Servlet对中文的处理GB2312 D6 D0 CE C4 
深入剖析关于JSP和Servlet对中文的处理(GB2312) E4 B8 AD E6 96 87 (UTF) \u4E2D\u6587 (在Unicode中=“中文”) 
深入剖析关于JSP和Servlet对中文的处理ISO-8859-1 D6 D0 CE C4 
深入剖析关于JSP和Servlet对中文的处理(GB2312) C3 96 C3 90 C3 8E C3 84 (UTF) \u00D6 \u00D0 \u00CE \u00C4 (在D6 D0 CE C4前面各加了一个00) 
深入剖析关于JSP和Servlet对中文的处理无(默认) D6 D0 CE C4 (GB2312) 同ISO-8859-1 同ISO-8859-1 
深入剖析关于JSP和Servlet对中文的处理
深入剖析关于JSP和Servlet对中文的处理  普通Java程序的编译过程与Servlet完全一样。
深入剖析关于JSP和Servlet对中文的处理
深入剖析关于JSP和Servlet对中文的处理  CLASS文件中的中文表示法是不是昭然若揭了?OK,接下来看看CLASS又是怎样输出中文的呢?
深入剖析关于JSP和Servlet对中文的处理
深入剖析关于JSP和Servlet对中文的处理  Class:输出字符串
深入剖析关于JSP和Servlet对中文的处理
深入剖析关于JSP和Servlet对中文的处理  上文说过,字符串在内存中表现为Unicode编码。至于这种Unicode编码表示了什么,那要看它是从哪种字符集映射过来的,也就是说要看它的祖先。这好比在托运行李时,外观都是纸箱子,里面装了什么就要看寄邮件的人实际邮了什么东西。
深入剖析关于JSP和Servlet对中文的处理
深入剖析关于JSP和Servlet对中文的处理  看看上面的例子,如果给一串Unicode编码“00D6 00D0 00CE 00C4”,如果不作转换,直接用Unicode码表来对照它时,是四个字符(而且是特殊字符);假如把它与“ISO8859-1”进行映射,则直接去掉前面的“00”即可得到“D6 D0 CE C4”,这是ASCII码表中的四个字符;而假如把它当作GB2312来进行映射,得到的结果很可能是一大堆乱码,因为在GB2312中有可能没有(也有可能有)字符与00D6等字符对应(如果对应不上,将得到0x3f,也就是问号,如果对应上了,由于00D6等字符太靠前,估计也是一些特殊符号,真正的汉字在Unicode中的编码从4E00开始)。
深入剖析关于JSP和Servlet对中文的处理
深入剖析关于JSP和Servlet对中文的处理  各位看到了,同样的Unicode字符,可以解释成不同的样子。当然,这其中有一种是我们期望的结果。以上例而论,“D6 D0 CE C4”应该是我们所想要的,当把“D6 D0 CE C4”输出到IE中时,用“简体中文”方式查看,就能看到清楚的“中文”两个字了。(当然了,如果你一定要用“西欧字符”来看,那也没办法,你将得不到任何有何时何地的东西)为什么呢?因为“00D6 00D0 00CE 00C4”本来就是由ISO8859-1转化过去的。
深入剖析关于JSP和Servlet对中文的处理
深入剖析关于JSP和Servlet对中文的处理
深入剖析关于JSP和Servlet对中文的处理  给出如下结论:
深入剖析关于JSP和Servlet对中文的处理
深入剖析关于JSP和Servlet对中文的处理  在Class输出字符串前,会将Unicode的字符串按照某一种内码重新生成字节流,然后把字节流输入,相当于进行了一步“String.getBytes(???)”操作。???代表某一种字符集。
深入剖析关于JSP和Servlet对中文的处理
深入剖析关于JSP和Servlet对中文的处理  如果是Servlet,那么,这种内码就是在HttpServletResponse.setContentType()方法中指定的内码,也就是上文定义的<Servlet-charset>。
深入剖析关于JSP和Servlet对中文的处理
深入剖析关于JSP和Servlet对中文的处理  如果是JSP,那么,这种内码就是在<%@ page contentType=""%>中指定的内码,也就是上文定义的<Jsp-charset>。
深入剖析关于JSP和Servlet对中文的处理
深入剖析关于JSP和Servlet对中文的处理  如果是Java程序,那么,这种内码就是file.encoding中指定的内码,默认为ISO8859-1。
深入剖析关于JSP和Servlet对中文的处理
深入剖析关于JSP和Servlet对中文的处理  当输出对象是浏览器时
深入剖析关于JSP和Servlet对中文的处理
深入剖析关于JSP和Servlet对中文的处理  以流行的浏览器IE为例。IE支持多种内码。假如IE接收到了一个字节流“D6 D0 CE C4”,你可以尝试用各种内码去查看。你会发现用“简体中文”时能得到正确的结果。因为“D6 D0 CE C4”本来就是简体中文中“中文”两个字的编码。
深入剖析关于JSP和Servlet对中文的处理
深入剖析关于JSP和Servlet对中文的处理  OK,完整地看一遍。
深入剖析关于JSP和Servlet对中文的处理
深入剖析关于JSP和Servlet对中文的处理  JSP:源文件为GB2312格式的文本文件,且JSP源文件中有“中文”这两个汉字
深入剖析关于JSP和Servlet对中文的处理
深入剖析关于JSP和Servlet对中文的处理  如果指定了<Jsp-charset>为GB2312,转化过程如下表。
深入剖析关于JSP和Servlet对中文的处理
深入剖析关于JSP和Servlet对中文的处理  表4 Jsp-charset = GB2312时的变化过程
深入剖析关于JSP和Servlet对中文的处理
深入剖析关于JSP和Servlet对中文的处理序号 步骤说明 结果 
深入剖析关于JSP和Servlet对中文的处理1 编写JSP源文件,且存为GB2312格式 D6 D0 CE C4
深入剖析关于JSP和Servlet对中文的处理(D6D0=中 CEC4=文) 
深入剖析关于JSP和Servlet对中文的处理2 jspc把JSP源文件转化为临时JAVA文件,并把字符串按照GB2312映射到Unicode,并用UTF格式写入JAVA文件中 E4 B8 AD E6 96 87 
深入剖析关于JSP和Servlet对中文的处理3 把临时JAVA文件编译成CLASS文件 E4 B8 AD E6 96 87 
深入剖析关于JSP和Servlet对中文的处理4 运行时,先从CLASS文件中用readUTF读出字符串,在内存中的是Unicode编码 4E 2D 65 87(在Unicode中4E2D=中 6587=文) 
深入剖析关于JSP和Servlet对中文的处理5 根据Jsp-charset=GB2312把Unicode转化为字节流 D6 D0 CE C4 
深入剖析关于JSP和Servlet对中文的处理6 把字节流输出到IE中,并设置IE的编码为GB2312(作者按:这个信息隐藏在HTTP头中) D6 D0 CE C4 
深入剖析关于JSP和Servlet对中文的处理7 IE用“简体中文”查看结果 “中文”(正确显示) 
深入剖析关于JSP和Servlet对中文的处理
深入剖析关于JSP和Servlet对中文的处理  如果指定了<Jsp-charset>为ISO8859-1,转化过程如下表。
深入剖析关于JSP和Servlet对中文的处理
深入剖析关于JSP和Servlet对中文的处理  表5 Jsp-charset = ISO8859-1时的变化过程
深入剖析关于JSP和Servlet对中文的处理
深入剖析关于JSP和Servlet对中文的处理序号 步骤说明 结果 
深入剖析关于JSP和Servlet对中文的处理1 编写JSP源文件,且存为GB2312格式 D6 D0 CE C4
深入剖析关于JSP和Servlet对中文的处理(D6D0=中 CEC4=文) 
深入剖析关于JSP和Servlet对中文的处理2 jspc把JSP源文件转化为临时JAVA文件,并把字符串按照ISO8859-1映射到Unicode,并用UTF格式写入JAVA文件中 C3 96 C3 90 C3 8E C3 84 
深入剖析关于JSP和Servlet对中文的处理3 把临时JAVA文件编译成CLASS文件 C3 96 C3 90 C3 8E C3 84 
深入剖析关于JSP和Servlet对中文的处理4 运行时,先从CLASS文件中用readUTF读出字符串,在内存中的是Unicode编码 00 D6 00 D0 00 CE 00 C4
深入剖析关于JSP和Servlet对中文的处理(啥都不是!!!) 
深入剖析关于JSP和Servlet对中文的处理5 根据Jsp-charset=ISO8859-1把Unicode转化为字节流 D6 D0 CE C4 
深入剖析关于JSP和Servlet对中文的处理6 把字节流输出到IE中,并设置IE的编码为ISO8859-1(作者按:这个信息隐藏在HTTP头中) D6 D0 CE C4 
深入剖析关于JSP和Servlet对中文的处理7 IE用“西欧字符”查看结果 乱码,其实是四个ASCII字符,但由于大于128,所以显示出来的怪模怪样 
深入剖析关于JSP和Servlet对中文的处理8 改变IE的页面编码为“简体中文” “中文”(正确显示) 
深入剖析关于JSP和Servlet对中文的处理
深入剖析关于JSP和Servlet对中文的处理  奇怪了!为什么把<Jsp-charset>设成GB2312和ISO8859-1是一个样的,都能正确显示?因为表4表5中的第2步和第5步互逆,是相互“抵消”的。只不过当指定为ISO8859-1时,要增加第8步操作,殊为不便。
深入剖析关于JSP和Servlet对中文的处理
深入剖析关于JSP和Servlet对中文的处理  再看看不指定<Jsp-charset> 时的情况。
深入剖析关于JSP和Servlet对中文的处理
深入剖析关于JSP和Servlet对中文的处理  表6 未指定Jsp-charset 时的变化过程
深入剖析关于JSP和Servlet对中文的处理
深入剖析关于JSP和Servlet对中文的处理序号 步骤说明 结果 
深入剖析关于JSP和Servlet对中文的处理1 编写JSP源文件,且存为GB2312格式 D6 D0 CE C4
深入剖析关于JSP和Servlet对中文的处理(D6D0=中 CEC4=文) 
深入剖析关于JSP和Servlet对中文的处理2 jspc把JSP源文件转化为临时JAVA文件,并把字符串按照ISO8859-1映射到Unicode,并用UTF格式写入JAVA文件中 C3 96 C3 90 C3 8E C3 84 
深入剖析关于JSP和Servlet对中文的处理3 把临时JAVA文件编译成CLASS文件 C3 96 C3 90 C3 8E C3 84 
深入剖析关于JSP和Servlet对中文的处理4 运行时,先从CLASS文件中用readUTF读出字符串,在内存中的是Unicode编码 00 D6 00 D0 00 CE 00 C4 
深入剖析关于JSP和Servlet对中文的处理5 根据Jsp-charset=ISO8859-1把Unicode转化为字节流 D6 D0 CE C4 
深入剖析关于JSP和Servlet对中文的处理6 把字节流输出到IE中 D6 D0 CE C4 
深入剖析关于JSP和Servlet对中文的处理7 IE用发出请求时的页面的编码查看结果 视情况而定。如果是简体中文,则能正确显示,否则,需执行表5中的第8步 
深入剖析关于JSP和Servlet对中文的处理
深入剖析关于JSP和Servlet对中文的处理  Servlet:源文件为JAVA文件,格式是GB2312,源文件中含有“中文”这两个汉字
深入剖析关于JSP和Servlet对中文的处理
深入剖析关于JSP和Servlet对中文的处理  如果<Compile-charset>=GB2312,<Servlet-charset>=GB2312
深入剖析关于JSP和Servlet对中文的处理
深入剖析关于JSP和Servlet对中文的处理  表7 Compile-charset=Servlet-charset=GB2312 时的变化过程
深入剖析关于JSP和Servlet对中文的处理
深入剖析关于JSP和Servlet对中文的处理序号 步骤说明 结果 
深入剖析关于JSP和Servlet对中文的处理1 编写Servlet源文件,且存为GB2312格式 D6 D0 CE C4
深入剖析关于JSP和Servlet对中文的处理(D6D0=中 CEC4=文) 
深入剖析关于JSP和Servlet对中文的处理2 用javac ?encoding GB2312把JAVA源文件编译成CLASS文件 E4 B8 AD E6 96 87 (UTF) 
深入剖析关于JSP和Servlet对中文的处理3 运行时,先从CLASS文件中用readUTF读出字符串,在内存中的是Unicode编码 4E 2D 65 87 (Unicode) 
深入剖析关于JSP和Servlet对中文的处理4 根据Servlet-charset=GB2312把Unicode转化为字节流 D6 D0 CE C4 (GB2312) 
深入剖析关于JSP和Servlet对中文的处理5 把字节流输出到IE中并设置IE的编码属性为Servlet-charset=GB2312 D6 D0 CE C4 (GB2312) 
深入剖析关于JSP和Servlet对中文的处理6 IE用“简体中文”查看结果 “中文”(正确显示) 
深入剖析关于JSP和Servlet对中文的处理
深入剖析关于JSP和Servlet对中文的处理  如果<Compile-charset>=ISO8859-1,<Servlet-charset>=ISO8859-1
深入剖析关于JSP和Servlet对中文的处理
深入剖析关于JSP和Servlet对中文的处理  表8 Compile-charset=Servlet-charset=ISO8859-1时的变化过程
深入剖析关于JSP和Servlet对中文的处理
深入剖析关于JSP和Servlet对中文的处理序号 步骤说明 结果 
深入剖析关于JSP和Servlet对中文的处理1 编写Servlet源文件,且存为GB2312格式 D6 D0 CE C4
深入剖析关于JSP和Servlet对中文的处理(D6D0=中 CEC4=文) 
深入剖析关于JSP和Servlet对中文的处理2 用javac ?encoding ISO8859-1把JAVA源文件编译成CLASS文件 C3 96 C3 90 C3 8E C3 84 (UTF) 
深入剖析关于JSP和Servlet对中文的处理3 运行时,先从CLASS文件中用readUTF读出字符串,在内存中的是Unicode编码 00 D6 00 D0 00 CE 00 C4 
深入剖析关于JSP和Servlet对中文的处理4 根据Servlet-charset=ISO8859-1把Unicode转化为字节流 D6 D0 CE C4 
深入剖析关于JSP和Servlet对中文的处理5 把字节流输出到IE中并设置IE的编码属性为Servlet-charset=ISO8859-1 D6 D0 CE C4 (GB2312) 
深入剖析关于JSP和Servlet对中文的处理6 IE用“西欧字符”查看结果 乱码(原因同表5) 
深入剖析关于JSP和Servlet对中文的处理7 改变IE的页面编码为“简体中文” “中文”(正确显示) 
深入剖析关于JSP和Servlet对中文的处理
深入剖析关于JSP和Servlet对中文的处理  如果不指定Compile-charset或Servlet-charset,其默认值均为ISO8859-1。
深入剖析关于JSP和Servlet对中文的处理
深入剖析关于JSP和Servlet对中文的处理  当Compile-charset=Servlet-charset时,第2步和第4步能互逆,“抵消”,显示结果均能正确。读者可试着写一下Compile-charset<>Servlet-charset时的情况,肯定是不正确的。
深入剖析关于JSP和Servlet对中文的处理
深入剖析关于JSP和Servlet对中文的处理  当输出对象是数据库时
深入剖析关于JSP和Servlet对中文的处理
深入剖析关于JSP和Servlet对中文的处理  输出到数据库时,原理与输出到浏览器也是一样的。本节只是Servlet为例,JSP的情况请读者自行推导。
深入剖析关于JSP和Servlet对中文的处理
深入剖析关于JSP和Servlet对中文的处理  假设有一个Servlet,它能接收来自客户端(IE,简体中文)的汉字字符串,然后把它写入到内码为ISO8859-1的数据库中,然后再从数据库中取出这个字符串,显示到客户端。
深入剖析关于JSP和Servlet对中文的处理
深入剖析关于JSP和Servlet对中文的处理  表9 输出对象是数据库时的变化过程(1)
深入剖析关于JSP和Servlet对中文的处理
深入剖析关于JSP和Servlet对中文的处理序号 步骤说明 结果 域 
深入剖析关于JSP和Servlet对中文的处理1 在IE中输入“中文” D6 D0 CE C4 IE 
深入剖析关于JSP和Servlet对中文的处理2 IE把字符串转变成UTF,并送入传输流中 E4 B8 AD E6 96 87 
深入剖析关于JSP和Servlet对中文的处理3 Servlet接收到输入流,用readUTF读取 4E 2D 65 87(unicode) Servlet 
深入剖析关于JSP和Servlet对中文的处理4 编程者在Servlet中必须把字符串根据GB2312还原为字节流 D6 D0 CE C4 
深入剖析关于JSP和Servlet对中文的处理5 编程者根据数据库内码ISO8859-1生成新的字符串 00 D6 00 D0 00 CE 00 C4 
深入剖析关于JSP和Servlet对中文的处理6 把新生成的字符串提交给JDBC 00 D6 00 D0 00 CE 00 C4 
深入剖析关于JSP和Servlet对中文的处理7 JDBC检测到数据库内码为ISO8859-1 00 D6 00 D0 00 CE 00 C4 JDBC 
深入剖析关于JSP和Servlet对中文的处理8 JDBC把接收到的字符串按照ISO8859-1生成字节流 D6 D0 CE C4 
深入剖析关于JSP和Servlet对中文的处理9 JDBC把字节流写入数据库中 D6 D0 CE C4 
深入剖析关于JSP和Servlet对中文的处理10 完成数据存储工作 D6 D0 CE C4 数据库 
深入剖析关于JSP和Servlet对中文的处理以下是从数据库中取出数的过程 
深入剖析关于JSP和Servlet对中文的处理11 JDBC从数据库中取出字节流 D6 D0 CE C4 JDBC 
深入剖析关于JSP和Servlet对中文的处理12 JDBC按照数据库的字符集ISO8859-1生成字符串,并提交给Servlet 00 D6 00 D0 00 CE 00 C4 (Unicode)   
深入剖析关于JSP和Servlet对中文的处理13 Servlet获得字符串 00 D6 00 D0 00 CE 00 C4 (Unicode) Servlet 
深入剖析关于JSP和Servlet对中文的处理14 编程者必须根据数据库的内码ISO8859-1还原成原始字节流 D6 D0 CE C4   
深入剖析关于JSP和Servlet对中文的处理15 编程者必须根据客户端字符集GB2312生成新的字符串 4E 2D 65 87
深入剖析关于JSP和Servlet对中文的处理(Unicode)   
深入剖析关于JSP和Servlet对中文的处理Servlet准备把字符串输出到客户端 
深入剖析关于JSP和Servlet对中文的处理16 Servlet根据<Servlet-charset>生成字节流 D6D0 CE C4 Servlet 
深入剖析关于JSP和Servlet对中文的处理17 Servlet把字节流输出到IE中,如果已指定<Servlet-charset>,还会设置IE的编码为<Servlet-charset> D6 D0 CE C4 
深入剖析关于JSP和Servlet对中文的处理18 IE根据指定的编码或默认编码查看结果 “中文”(正确显示) IE 
深入剖析关于JSP和Servlet对中文的处理
深入剖析关于JSP和Servlet对中文的处理  解释一下,表中第4第5步和第15第16步是用红色标记的,表示要由编码者来作转换。第4、5两步其实就是一句话:“new String(source.getBytes("GB2312"), "ISO8859-1")”。第15、16两步也是一句话:“new String(source.getBytes("ISO8859-1"), "GB2312")”。亲爱的读者,你在这样编写代码时是否意识到了其中的每一个细节呢?
深入剖析关于JSP和Servlet对中文的处理
深入剖析关于JSP和Servlet对中文的处理  至于客户端内码和数据库内码为其它值时的流程,和输出对象是系统控制台时的流程,请读者自己想吧。明白了上述流程的原理,相信你可以轻松地写出来。
深入剖析关于JSP和Servlet对中文的处理
深入剖析关于JSP和Servlet对中文的处理  行文至此,已可告一段落了。终点又回到了起点,对于编程者而言,几乎是什么影响都没有。
深入剖析关于JSP和Servlet对中文的处理
深入剖析关于JSP和Servlet对中文的处理  因为我们早就被告之要这么做了。
深入剖析关于JSP和Servlet对中文的处理
深入剖析关于JSP和Servlet对中文的处理  以下给出一个结论,作为结尾。
深入剖析关于JSP和Servlet对中文的处理
深入剖析关于JSP和Servlet对中文的处理  1、 在Jsp文件中,要指定contentType,其中,charset的值要与客户端浏览器所用的字符集一样;对于其中的字符串常量,不需做任何内码转换;对于字符串变量,要求能根据ContentType中指定的字符集还原成客户端能识别的字节流,简单地说,就是“字符串变量是基于<Jsp-charset>字符集的”;
深入剖析关于JSP和Servlet对中文的处理
深入剖析关于JSP和Servlet对中文的处理  2、 在Servlet中,必须用HttpServletResponse.setContentType()设置charset,且设置成与客户端内码一致;对于其中的字符串常量,需要在Javac编译时指定encoding,这个encoding必须与编写源文件的平台的字符集一样,一般说来都是GB2312或GBK;对于字符串变量,与JSP一样,必须“是基于<Servlet-charset>字符集的”。
深入剖析关于JSP和Servlet对中文的处理

相关文章:

  • 2021-11-28
  • 2021-11-10
  • 2021-05-28
  • 2022-12-23
  • 2022-12-23
  • 2021-11-29
  • 2021-10-25
猜你喜欢
  • 2022-12-23
  • 2021-10-14
  • 2022-12-23
  • 2022-12-23
  • 2021-07-26
相关资源
相似解决方案