进入javaweb学习以来,很深的感触就是中国文字太博大精深了,对于初学者的我,中文乱码问题困扰我很久,昨晚做项目做到两点,今天实在太困乏了,窝在暖暖的屋子里,好想就这样睡过去,不过想到冯老师给我们的忠告,还是放弃了堕落的想法,为了赶走了困意,还是做点学习总结吧。
中文乱码虽然不能算是一个很大的课题,但是我想通过我个人一些浅显的理解给那些和我一样初学的友人提供一点点帮助吧。
一、常见的字符编码
ISO-8859-1 :单字节编码。字符范围0-255,应用于英文。
Cp1252,美国英语编码,同ANSI标准编码
unicode:定长双字节,不兼容ISO-8859-1编码。
UTF-8:不定长,每一个字符的长度从1-6个字节不等,有简单校验功能。
GB2312:双字节编码,专门表示汉字,只能表示简单汉字 ,是GBK的子集
GBK : 可以表示繁体字和简体字
二、中文乱码问题的来源
计算机最初的操作系统支持的编码是单字节的字符编码,于是,在计算机中一切处理程序最初都是以单字节编码的英文为准进行处理。随着计算机的发展,为了适应世界其它民族的语言(当然包括我们的汉字),人们提出了UNICODE编码,它采用双字节编码,兼容英文字符和其它民族的双字节字符编码,所以,目前,大多数国际性的软件内部均采用UNICODE编码(后来出现了utf-8),在软件运行时,它获得本地支持系统(多数时间是操作系统)默认支持的编码格式,然后再将软件内部的UNICODE转化为本地系统默认支持的格式显示出来。Java的JDK和JVM即是如此,而汉字是双字节编码语言,为了能让计算机处理中文,我们自己制定的gb2312、GBK、GBK2K等标准以适应计算机处理的需求。所以,大部分的操作系统为了适应我们处理中文的需求,均定制有中文操作系统,它们采用的是GBK,GB2312编码格式以正确显示我们的汉字。所以出现中文乱码可能情况:
1、Java(包括JSP)源文件中很可能包含有中文,而Java和JSP源文件的保存方式是基于字节流的,如果Java和JSP编译成class文件过程中,使用的编码方式与源文件的编码不一致,就会出现乱码。
2.将widows上编写的java程序移植到linux上可能导致
3.Java程序与其他存储媒介交互时产生的乱码。很多存储媒介,如数据库,文件,流等的存储方式都是基于字节流的,Java程序与这些媒介交互时就会发生字符(char)与字节(byte)之间的转换,具体情况如下:
从页面form提交数据到java程序 byte->char
从java程序到页面显示 char->byte
从数据库到java程序 byte ->char
从java程序到数据库 char->byte
从文件到java程序 byte->char
从java程序到文件 char->byte
从流到java程序 byte->char
从java程序到流 char->byte
如果在以上转换过程中使用的编码方式与字节原有的编码不一致,很可能就会出现乱码。
三、各种情况下乱码的解决办法
上面简单说明了一下中文乱码的问题,下面来看一看在各种不同的情况下究竟怎样解决呢?
1. 针对直接在控制台上运行的类
运行过程是这样的:首先java启动JVM,此时JVM读出操作系统中保存的class文件并把内容读入内存中,此时内存中为UNICODE格式的class类,然后JVM运行它,如果此时此类需要接收用户输入,则类会默认用file.encoding编码格式对用户输入的串进行编码并转化为unicode保存入内存(用户可以设置输入流的编码格式)。程序运行后,产生的字符串(UNICODE编码的)再回交给JVM,最后JRE把此字符串再转化为file.encoding格式(用户可以设置输出流的编码格式)传递给操作系统显示接口并输出到界面上。
小结:通过InputStreamReader和OutputStreamWriter来控制入口和出口。或者,在编译程序时,我们用以下方式来进行:
javac -encoding gb2312 Read.java
2. Servlet类中的乱码
在编译Servlet类的源程序时,在向用户输出时的编码部分用response对象的setContentType("text/html;charset=GBK");或gb2312来设置输出编码格式,同样在接收用户输入时,我们用request.setCharacterEncoding("GB2312")设置输入编码格式。
注意:1)一定要在使用request或response对象前设置。
2)tomcat的j2ee实现对表单提交即post方式提示时处理参数采用缺省的iso-8859-1来处理,tomcat对get方式提交的请求对query-string 处理时采用了和post方法不一样的处理方式,所以上面的方法只对post方式有效,如果是get方式的话,我们只能通过java.net.EnCoder和java.net.Decoder两个类来进行相关编码解码,在接受的页面我们也可以使用new String(byte[] bytes, String charsetName)配合getBytes方法接受。在form标签中设置accept-charset。一般默认网页的编码。
附:Get方式提交表单解决乱码方式二:
通过一个Filter.设置处理字符集为GBK。
1)在web.xml中加入下面几行
<filter>
<filter-name>Set Character Encoding</filter-name>
<filter-class>filters.SetCharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>GBK</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>Set Character Encoding</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
2)打开tomcat的server.xml文件中Connector,找到区块,加入如下一行:
URIEncoding=”GBK”
3.jap页面相关问题
1)jsp编译
<@page pageEncoding=”GB2312”> 设置jsp页面存储的编码方式
2)jsp输出
<@page contentType=”text/html; charset=GB2312”> 设置jsp页面输出到浏览器的编码方式。
3)静态网页中的乱码
通过META设置:<META http-equiv=”Content-Type” content=”text/html” charset=”GB2312”>
解决这类乱码问题的基本方法是在页面获取参数之前,强制指定request获取参数的编码方式:request.setCharacterEncoding("GBK")或request.setCharacterEncoding("gb2312").
如果在JSP将变量输出到页面时出现了乱码,可以通过设置response.setContentType("text/html;charset=GBK")或response.setContentType("text/html;charset=gb2312")解决。