java中文乱码字符集解决大全1

上传人:公**** 文档编号:569358348 上传时间:2024-07-29 格式:PDF 页数:14 大小:420.37KB
返回 下载 相关 举报
java中文乱码字符集解决大全1_第1页
第1页 / 共14页
java中文乱码字符集解决大全1_第2页
第2页 / 共14页
java中文乱码字符集解决大全1_第3页
第3页 / 共14页
java中文乱码字符集解决大全1_第4页
第4页 / 共14页
java中文乱码字符集解决大全1_第5页
第5页 / 共14页
点击查看更多>>
资源描述

《java中文乱码字符集解决大全1》由会员分享,可在线阅读,更多相关《java中文乱码字符集解决大全1(14页珍藏版)》请在金锄头文库上搜索。

1、1 java 中文解决大全 Abstract: 本文深入分析了Java 程序设计中Java 编译器对java 源文件和JVM 对 class 类文件的编码/解码过程,通过此过程的解析透视出了Java 编程中中文问题产生的根本原因,最后给出了建议的最优化的解决Java 中文问题的方法。 1. 中文问题的来源 计算机最初的操作系统支持的编码是单字节的字符编码,于是,在计算机中一切处理程序最初都是以单字节编码的英文为准进行处理。随着计算机的发展,为了适应世界其它民族的语言(当然包括我们的汉字),人们提出了UNICODE 编码,它采用双字节编码,兼容英文字符和其它民族的双字节字符编码,所以,目前,大多

2、数国际性的软件内部均采用UNICODE 编码,在软件运行时,它获得本地支持系统(多数时间是操作系统)默认支持的编码格式,然后再将软件内部的UNICODE 转化为本地系统默认支持的格式显示出来。Java 的 JDK 和 JVM 即是如此,我这里说的JDK 是指国际版的JDK,我们大多数程序员使用的是国际化的JDK 版本,以下所有的JDK 均指国际化的JDK 版本。我们的汉字是双字节编码语言,为了能让计算机处理中文,我们自己制定的gb2312、 GBK、 GBK2K 等标准以适应计算机处理的需求。所以,大部分的操作系统为了适应我们处理中文的需求,均定制有中文操作系统,它们采用的是GBK,GB231

3、2 编码格式以正确显示我们的汉字。如: 中文Win2K默认采用的是GBK 编码显示,在中文WIN2k 中保存文件时默认采用的保存文件的编码格式也是GBK 的,即,所有在中文WIN2K中保存的文件它的内部编码默认均采用GBK 编码,注意:GBK 是在GB2312 基础上扩充来的。 由于Java 语言内部采用UNICODE 编码,所以在JAVA 程序运行时,就存在着一个从UNICODE 编码和对应的操作系统及浏览器支持的编码格式转换输入、输出的问题,这个转换过程有着一系列的步骤,如果其中任何一步出错,则显示出来的汉字就会出是乱码,这就是我们常见的JAVA 中文问题。 同时,Java 是一个跨平台的

4、编程语言,也即我们编写的程序不仅能在中文windows 上运行,也能在中文Linux 等系统上运行, 同时也要求能在英文等系统上运行(我们经常看到有人把在中文win2k 上编写的JAVA 程序,移植到英文Linux 上运行)。这种移植操作也会带来中文问题。 还有,有人使用英文的操作系统和英文的IE 等浏览器,来运行带中文字符的程序和浏览中文网页,它们本身就不支持中文,也会带来中文问题。 几乎所有的浏览器默认在传递参数时都是以UTF-8 编码格式来传递,而不是按中文编码传递,所以,传递中文参数时也会有问题,从而带来乱码现象。 总之,以上几个方面是JAVA 中的中文问题的主要来源,我们把以上原因造

5、成的程序不能正确运行而产生的问题称作:JAVA 中文问题。 2 2. JAVA 编码转换的详细过程 我们常见的JAVA 程序包括以下类别: *直接在console 上运行的类(包括可视化界面的类) *JSP 代码类(注:JSP 是 Servlets 类的变型) *Servelets 类 *EJB 类 *其它不可以直接运行的支持类 这些类文件中,都有可能含有中文字符串,并且我们常用前三类JAVA 程序和用户直接交互,用于输出和输入字符,如:我们在JSP 和 Servlet 中得到客户端送来的字符,这些字符也包括中文字符。无论这些JAVA 类的作用如何,这些JAVA 程序的生命周期都是这样的: *

6、编程人员在一定的操作系统上选择一个合适的编辑软件来实现源程序代码并以.java 扩展名保存在操作系统中,例如我们在中文win2k 中用记事本编辑一个java 源程序; *编程人员用JDK 中的javac.exe 来编译这些源代码,形成.class 类 (JSP 文件是由容器调用JDK 来编译的); *直接运行这些类或将这些类布署到WEB容器中去运行,并输出结果。 那么,在这些过程中,JDK 和 JVM 是如何将这些文件如何编码和解码并运行的呢? 这里,我们以中文win2k 操作系统为例说明JAVA 类是如何来编码和被解码的。 第一步,我们在中文win2k 中用编辑软件如记事本编写一个Java

7、源程序文件(包括以上五类JAVA 程序), 程序文件在保存时默认采用了操作系统默认支持GBK 编码格式(操作系统默认支持的格式为file.encoding 格式)形成了一个.java 文件,也即,java 程序在被编译前,我们的JAVA 源程序文件是采用操作系统默认支持的file.encoding 编码格式保存的,java 源程序中含有中文信息字符和英文程序代码;要查看系统的file.encoding 参数,可以用以下代码: public class ShowSystemDefaultEncoding public static void main(String args) String en

8、coding = System.getProperty(file.encoding); System.out.println(encoding); 第二步,我们用JDK 的 javac.exe 文件编译我们的Java 源程序,由于JDK 是国际版的,在编译的时候,如果我们没有用-encoding 参数指定我们的JAVA 源程序的编码格式,则javac.exe 首先获得我们操作系统默认采用的编码格式,也即在编译java 程序时,若我们不指定源程序文件的编码格式,JDK 首先获得操作系统的file.encoding 参数(它保存的就是操作系统默认的编码格式,如WIN2k,它的值为GBK),然后JD

9、K 就把我们的java 源程序从file.encoding 编码格式转化为JAVA 内部默认的 UNICODE 格式放入内存中。然后,javac 把转换后的unicode 格式的文件进行编译成.class 类文件,此时.class 文件是UNICODE 编码的,它暂放在内存中,紧接着,JDK 将此以UNICODE 编码的编译后的class 文件保存到我们的操作系统中形3 成我们见到的.class 文件。对我们来说,我们最终获得的.class 文件是内容以UNICODE 编码格式保存的类文件,它内部包含我们源程序中的中文字符串,只不过此时它己经由file.encoding 格式转化为UNICOD

10、E 格式了。 这一步中,对于JSP 源程序文件是不同的,对于JSP,这个过程是这样的:即 WEB容器调用JSP 编译器,JSP 编译器先查看 JSP 文件中是否设置有文件编码格式,如果JSP 文件中没有设置JSP 文件的编码格式,则 JSP 编译器调用JDK 先把JSP 文件用JVM 默认的字符编码格式(也即WEB容器所在的操作系统的默认的file.encoding)转化为临时的Servlet 类,然后再把它编译成UNICODE 格式的class 类,并保存在临时文件夹中。如:在中文win2k 上,WEB容器就把JSP 文件从GBK 编码格式转化为UNICODE 格式,然后编译成临时保存的Se

11、rvlet 类,以响应用户的请求。 第三步,运行第二步编译出来的类,分为三种情况: A、 直接在console 上运行的类 B、 EJB类和不可以直接运行的支持类(如 JavaBean 类 ) C、 JSP 代码和Servlet 类 D、 JAVA 程序和数据库之间 下面我们分这四种情况来看。 a) 直接在console 上运行的类 这种情况,运行该类首先需要JVM 支持,即操作系统中必须安装有JRE。运行过程是这样的:首先java 启动JVM,此时JVM 读出操作系统中保存的class 文件并把内容读入内存中,此时内存中为UNICODE 格式的class 类,然后JVM 运行它,如果此时此类

12、需要接收用户输入,则类会默认用file.encoding 编码格式对用户输入的串进行编码并转化为unicode 保存入内存(用户可以设置输入流的编码格式)。程序运行后,产生的字符串(UNICODE 编码的)再回交给JVM,最后JRE 把此字符串再转化为file.encoding 格式(用户可以设置输出流的编码格式)传递给操作系统显示接口并输出到界面上。 对于这种直接在console 上运行的类,它的转化过程可用图1 更加明确的表示出来: 图 1 4 以上每一步的转化都需要正确的编码格式转化,才能最终不出现乱码现象。 b) EJB 类和不可以直接运行的支持类(如 JavaBean 类 ) 由于E

13、JB 类和不可以直接运行的支持类,它们一般不与用户直接交互输入和输出,它们常常与其它的类进行交互输入和输出,所以它们在第二步被编译后,就形成了内容是UNICODE 编码的类保存在操作系统中了,以后只要它与其它的类之间的交互在参数传递过程中没有丢失,则它就会正确的运行。 这种EJB类和不可以直接运行的支持类, 它的转化过程可用图2 更加明确的表示出来: 图 2 5 c) JSP 代码和Servlet 类 经过第二步后,JSP 文件也被转化为Servlets 类文件,只不过它不像标准的Servlets 一校存在于classes 目录中,它存在于WEB容器的临时目录中,故这一步中我们也把它做为Ser

14、vlets 来看。 对于Servlets,客户端请求它时,WEB容器调用它的JVM 来运行Servlet,首先,JVM 把 Servlet 的 class 类从系统中读出并装入内存中,内存中是以UNICODE 编码的Servlet 类的代码,然后JVM 在内存中运行该Servlet 类,如果Servlet 在运行的过程中,需要接受从客户端传来的字符如:表单输入的值和URL 中传入的值,此时如果程序中没有设定接受参数时采用的编码格式,则 WEB容器会默认采用ISO-8859-1 编码格式来接受传入的值并在JVM 中转化为UNICODE 格式的保存在WEB容器的内存中。Servlet 运行后生成输

15、出,输出的字符串是UNICODE 格式的,紧接着,容器将Servlet 运行产生的UNICODE 格式的串(如html 语法,用户输出的串等)直接发送到客户端浏览器上并输出给用户,如果此时指定了发送时输出的编码格式,则按指定的编码格式输出到浏览器上,如果没有指定,则默认按ISO-8859-1 编码发送到客户的浏览器上。这种JSP 代码和Servlet 类,它的转化过程可用图3 更加明确地表示出来: 图 3 6 d) Java 程序和数据库之间 对于几乎所有数据库的JDBC 驱动程序,默认的在JAVA 程序和数据库之间传递数据都是以ISO-8859-1 为默认编码格式的,所以,我们的程序在向数据

16、库内存储包含中文的数据时,JDBC 首先是把程序内部的UNICODE 编码格式的数据转化为ISO-8859-1 的格式,然后传递到数据库中,在数据库保存数据时,它默认即以ISO-8859-1 保存,所以,这是为什么我们常常在数据库中读出的中文数据是乱码。 对于JAVA 程序和数据库之间的数据传递,我们可以用图4 清晰地表示出来 图 4 3. 分析常见的JAVA 中文问题几个必须清楚的原则 首先,经过上面的详细分析,我们可以清晰地看到,任何JAVA 程序的生命期中,其编码转换的关键过程是在于:最初编译成class 文件的转码和最终向用户输出的转码过程。 其次,我们必须了解JAVA 在编译时支持的

17、、常用的编码格式有以下几种: *ISO-8859-1, 8-bit, 同 8859_1,ISO-8859-1,ISO_8859_1 等编码 *Cp1252,美国英语编码,同ANSI 标准编码 *UTF-8,同unicode 编码 *GB2312,同gb2312-80,gb2312-1980 等编码 *GBK , 同 MS936,它是gb2312 的扩充 及其它的编码,如韩文、日文、繁体中文等。同时,我们要注意这些编码间的兼容关体系如下: unicode 和 UTF-8 编码是一一对应的关系。GB2312 可以认为是GBK 的子集,即 GBK 编码是在gb2312 上扩展来的。同时,GBK 编码

18、包含了20902 个汉字,编码范围为:0x8140-0xfefe,所有的字符可以一一对应到UNICODE2.0 中来。 再次,对于放在操作系统中的.java 源程序文件,在编译时,我们可以指定它内容的编码格式,具体来说用-encoding 来指定。注意:如果源程序中含有中文字符,而你用-encoding 指定为其它的编码字符,显然是要出错的。用-encoding 指定源文件的编码方式为GBK 或 gb2312,无论我们在什么系统上编译含有中文字符的JAVA 源程序都不会有问题,它都会正确地将中7 文转化为UNICODE 存储在class 文件中。 然后,我们必须清楚,几乎所有的WEB容器在其内

19、部默认的字符编码格式都是以ISO-8859-1 为默认值的,同时,几乎所有的浏览器在传递参数时都是默认以UTF-8 的方式来传递参数的。所以,虽然我们的Java 源文件在出入口的地方指定了正确的编码方式,但其在容器内部运行时还是以ISO-8859-1 来处理的。 4. 中文问题的分类及其建议最优解决办法 了解以上JAVA 处理文件的原理之后,我们就可以提出了一套建议最优的解决汉字问题的办法。 我们的目标是:我们在中文系统中编辑的含有中文字符串或进行中文处理的JAVA 源程序经编译后可以移值到任何其它的操作系统中正确运行,或拿到其它操作系统中编译后能正确运行,能正确地传递中文和英文参数,能正确地

20、和数据库交流中英文字符串。 我们的具体思路是:在 JAVA 程序转码的入口和出口及JAVA 程序同用户有输入输出转换的地方限制编码方法使之正确即可。 具体解决办法如下: 1) 针对直接在console 上运行的类 对于这种情况,我们建议在程序编写时,如果需要从用户端接收用户的可能含有中文的输入或含有中文的输出,程序中应该采用字符流来处理输入和输出,具体来说,应用以下面向字符型节点流类型: 对文件:FileReader, FileWrieter 其字节型节点流类型为:FileInputStream, FileOutputStream 对内存(数组):CharArrayReader, CharAr

21、rayWriter 其字节型节点流类型为:ByteArrayInputStream, ByteArrayOutputStream 对内存(字符串):StringReader, StringWriter 对管道:PipedReader, PipedWriter 其字节型节点流类型为:PipedInputStream, PipedOutputStream 同时,应该用以下面向字符型处理流来处理输入和输出: BufferedWriter, BufferedReader 其字节型的处理流为:BufferedInputeStream, BufferedOutputStream InputStreamRe

22、ader, OutputStreamWriter 其字节型的处理流为:DataInputStream, DataOutputStream 其中InputStreamReader 和 InputStreamWriter 用于将字节流按照指定的字符编码集转换到字符流,如: InputStreamReader in = new InputStreamReader(System.in , GB2312); OutputStreamWriter out = new OutputStreamWriter (System.out, GB2312); 例如:采用如下的示例JAVA 编码就达到了要求: 8 /R

23、ead.java import java.io.*; public class Read public static void main(String args) throws IOException String str = n中文测试,这是内部硬编码的串+ntest english character; String strin= ; BufferedReader stdin = new BufferedReader(new InputStreamReader(System.in,gb2312); /设置输入接口按中文编码 BufferedWriter stdout = new Buffe

24、redWriter(new OutputStreamWriter(System.out,gb2312); /设置输出接口按中文编码 stdout.write(请输入:); stdout.flush(); strin = stdin.readLine(); stdout.write(这是从用户输入的串:+strin); stdout.write(str); stdout.flush(); 同时,在编译程序时,我们用以下方式来进行: javac -encoding gb2312 Read.java 其运行结果如图5 所示: 图 5 2) 针对EJB 类和不可以直接运行的支持类(如 JavaBean

25、 类 ) 由于这种类它们本身被其它的类调用,不直接与用户交互,故对这种类来说,我们的建议的处理方式是内部程序中应该采用字符流来处理程序内部的中文字符串(具体如上面一节中一样), 同时,在编译类时用-encoding gb2312 参数指示源文件是中文格式编码的即可。 9 3) 针对Servlet 类 针对Servlet,我们建议用以下方法: 在编译Servlet 类的源程序时,用-encoding 指定编码为GBK 或 GB2312,且在向用户输出时的编码部分用response 对象的setContentType(text/html;charset=GBK);或 gb2312 来设置输出编码格

26、式,同样在接收用户输入时,我们用request.setCharacterEncoding(GB2312);这样无论我们的servlet 类移植到什么操作系统中,只有客户端的浏览器支持中文显示,就可以正确显示。如下是一个正确的示例: /HelloWorld.java package hello; import java.io.*; import javax.servlet.*; import javax.servlet.http.*; public class HelloWorld extends HttpServlet public void init() throws ServletExce

27、ption public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException request.setCharacterEncoding(GB2312); / 设置输入编码格式 response.setContentType(text/html;charset=GB2312); / 设置输出编码格式 PrintWriter out = response.getWriter(); / 建议使用PrintWriter 输出 out.print

28、ln(); out.println(Hello World! This is created by Servlet!测试中文!); out.println(); public void doPost(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException request.setCharacterEncoding(GB2312); / 设置输入编码格式 response.setContentType(text/html;charset=GB2312); /设置输出

29、编码格式 String name = request.getParameter(name); String id = request.getParameter(id); if(name=null) name=; if(id=null) id=; PrintWriter out = response.getWriter(); / 建议使用PrintWriter 输出 out.println(); out.println(你传入的中文字串是: + name); 10 out.println(你输入的 id 是: + id); out.println(); public void destroy()

30、 请用 javac -encoding gb2312 HelloWorld.java 来编译此程序。 测试此 Servlet 的程序如下所示: function Submit() /通过 URL 传递中文字符串值给 Servlet document.base.action = ./HelloWorld?name=中文; document.base.method = POST; document.base.submit(); 传给 Servlet 其运行结果如图 6 所示: 11 图 6 4) JAVA 程序和数据库之间 为避免JAVA 程序和数据库之间数据传递出现乱码现象,我们建议采用以下最优

31、方法来处理: 1、 对于JAVA 程序的处理方法按我们指定的方法处理。 2、 把数据库默认支持的编码格式改为GBK 或 GB2312 的。 如:在mysql 中,我们可以在配置文件my.ini 中加入以下语句实现: 在 mysqld区增加: default-character-set=gbk 并增加: client default-character-set=gbk 在 SQL Server2K 中,我们可以将数据库默认的语言设置为Simplified Chinese 来达到目的。 5) 针对JSP 代码 由于JSP 是在运行时,由WEB容器进行动态编译的,如果我们没有指定JSP 源文件的编码

32、格式,则JSP 编译器会获得服务器操作系统的file.encoding 值来对JSP 文件编译的,它在移植时最容易出问题,如在中文win2k 中可以很好运行的jsp 文件拿到英文linux 中就不行,尽管客户端都是一样的,那是因为容器在编译JSP 文件时获取的操作系统的编码不同造成的(在中文wink 中的file.encoding 和在英文Linux 中 file.encoding 是不同的,且英文Linux 的 file.encoding 对中文不支持,所以编译出来的JSP 类就会有问题)。网络上讨论的大多数是此类问题,多是因为JSP 文件移植平台时不能正确显示的问题,对于这类问题,我们了解

33、了JAVA 中程序编码转换的原理,解决起来就容易多了。我们建议的解决办法如下: 12 1、我们要保证 JSP 向客户端输出时是采用中文编码方式输出的,即无论如何我们首先在我们的 JSP 源代编中加入以下一行: 2、为了让 JSP 能正确获得传入的参数,我们在 JSP 源文件头加入下面一句: 3、为了让 JSP 编译器能正确地解码我们的含有中文字符的 JSP 文件,我们需要在 JSP 源文件中指定我们的 JSP 源文件的编码格式,具体来说,我们在 JSP 源文件头上加入下面的一句即可: 或 这是 JSP 规范 2.0 新增加的指令。 我们建议使用此方法来解 JSP 文件中的中文问题,下面的代码是

34、一个正确做法的 JSP 文件的测试程序: /testchinese.jsp function Submit() document.base.action = ?ACTION=SENT&str=传入的中文; document.base.method = POST; document.base.submit(); 13 提交 % if(action!=null & action.equals(SENT) out.println(你输入的字符为:+name); out.println(你通过URL 传入的字符为:+str); % 如图7 是此程序运行的结果示意图: 图 7 5. 总结 在上面的详细分析中,我们清晰地给出了JAVA 在处理源程序过程中的详细转换过程,为我们正确解决JAVA 编程中的中文问题提供了基础。同时,我们给出了认为是最优的解决JAVA 中文问题的办法。 14

展开阅读全文
相关资源
正为您匹配相似的精品文档
相关搜索

最新文档


当前位置:首页 > 建筑/环境 > 施工组织

电脑版 |金锄头文库版权所有
经营许可证:蜀ICP备13022795号 | 川公网安备 51140202000112号