关于中文编码的乱码问题是我们中国人永远的痛,呵呵,不无道理,因为在太多的场合,我们中国人并没有占据主导地位,所以作为一个程序员,对于汉字的编码问题就一直让人头疼。程序在显示过程中总是在不经意的时候出来一乱码,究其根本原因是汉字的编码没一统世界,究其次要原因则是我们对程序显示过程理解不够透彻。根本原因我们无法改变,所以只能在次要原因上下功夫了,下面我就以我这两天的心得总结下:
1、在html页面上的乱码:
<html>
<head>
<title>小例子</title>
</head>
<body>
这里是中文字!
</body>
</html>
这么简单的程序应该不会有什么错吧,可是结果 却是:�����������֣� 这么个东东,到底是什么原因呢?究其原因这个关乎浏览器显示文字的原理了。大家都知道任何东西在计算机的存储都是以0和1的方式存储的,那么当我们把上述文本存在计算机上时,它们是怎么变成0和1的呢?这涉及到了字符的编码了,我们常用的有我国的gb2312,国际通用的UTF-8和美国的ISO8859-1,而记事本当我们存储时则是默认按照我国的gb2312,当这些0和1在计算机上交给浏览器显示时,浏览器也会有自己的编码方式把它们转换回来显示成功,显而易见,只有这两者的编码方式相同时才可以正确显示我们想让它显示的数据,而恰恰不巧的是这时候我这台计算机上两者的编码方式是不同的,所以出现了乱码现象。问题原因出来了,那么解决办法也就清楚了:修改记事本或者浏览器其中一个的编码方式与另外一个想同即可!
2、servlet程序response中显示出现乱码的情况,下面是一简单servlet程序:
public class Demo extends HttpServlet {
private static final long serialVersionUID = 1L;
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
String data="中文";
OutputStream out=response.getOutputStream();
out.write(data.getBytes());
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
this.doGet(request, response);
}
}
这个程序作用只是通过servlet程序把“中文”打印到浏览器显示,运行后结果为:�й 再次出现了乱码状况,这次又是啥原因呢?那我们就再从根分析下乱码的根本原因。当servlet(服务器)从客户端获取一些中文数据,然后经过处理再次显示在浏览器这个过程同样发生几次中文数据与01之间的相互转换。
首先:servlet要想把“中文”写给浏览器,先要把其变为字节:data.getBytes());
而getBytes());方法默认的是使用本地字符集:gb2312进行编码,于是便以gb2312编码把“中文”传递给了浏览器,浏览器收到这些0和1同样要进行编码然后显示正确的数据给客户,不巧的是浏览器此时设置的编码方式非gb2312,所以导致了乱码的出现。
此时解决方法之一:改变其中之一的编码方式与另外一个相同即可,(假设浏览器编码为UTF-8)则改data.getBytes("UTF-8");或者改变浏览器的编码方式为gb2312;
但此时又牵扯出来一个问题,在实际开发中我们是不知道客户的浏览器的编码格式的,并且我们也不可能通知所有那些浏览我们服务器数据的客户都去修改浏览器的编码方式来防止看我们网页时出现乱码,当浏览器端编码不确定,服务器端编码可控制情况下,似乎问题就成了如何在服务器端控制浏览器打开时的编码格式。
这时我们倒有了另外一种解决方法:可以通过服务器发送给浏览器一个消息头控制浏览器的行为即:
response.setHeader("content-type","text/html;charset=UTF-8");这是利用response本身的性质来改变浏览器的编码,还有另一种变相的方式:我们还可以利用浏览器自己的特点,在html中有个meta标签,而其中的内容可以设置浏览器编码,所以我们还可以通过服务器发送一个meta标签给浏览器:response.getOutputStream().write("<meta http-equiv='content-type' content='text/html;charset=UTF-8'>".getBytes());因为发送的这段内容的特殊性,所以同样达到了目的;
sun公司同时还提供了另外一种方式直接控制浏览器编码:response.setContentType("text/html;charset=UTF-8");
这里还有两个小问题:
一是:我们除了可以以字节流方式outputstream给浏览器输数据外还可以以字符流方式输出response.getWriter();这里同时涉及到了服务器端编码的控制,可以调用response.setCharacterEncoding("UTF-8");方法控制。
二是:我们向浏览器写int型数据问题:out.write(170);直接这么输出结果也会乱码,原因就是:服务器向浏览器传送数据过程中只经过了一次编码过程,即对170服务器并没按照某编码格式进行编码,而传到浏览器时,浏览器却会将其依照自己的编码格式进行编码,结果必然是错的,所以在传递数字时不妨可以将其变为字符串的形式进行传递如:out.write((170+"").getBytes());
3、request服务器响应客户机时的乱码问题:
当从浏览器提交一个中文数据比如还是“中文”给服务器时,
客户端的程序如下:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>form.html</title>
<meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
<meta http-equiv="description" content="this is my page">
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
</head>
<body>
<form action="/fday06/servlet/RequestDemo2" method="post">
<input type="text" name="username"/><br/>
<input type="submit" value="提交">
</form>
</body>
</html>
处理客户机请求的服务器端为:
package cn.itcast.request;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class RequestDemo2 extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
String username=request.getParameter("username");
System.out.println(username);
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
this.doGet(request, response);
}
}
打印结果为:?????? 乱码,这次的原因不用说,肯定又是多次编码不一致造成的,可是又该怎么解决呢?这次从客户端程序 <meta http-equiv="content-type" content="text/html; charset=UTF-8">可以看出客户端是采用UTF-8编码的,可是服务器端该怎么控制?——request.setCharacterEncoding("UTF-8");通过这个方法控制!但是这里面还隐藏着一个问题:这个方法只对于post提交方法有效,而对于大多数的get方法是无效的,那么对于get方法貌似没有更好的方法,只能是手工解决,浏览器端采用UTF-8,服务器端的username=request.getParameter("username");得到的这个username则是按照美国人喜欢的ISO8859-1编码的,所以只能将username反向编码重新得到原始数据了:
username=new String(username.getBytes("ISO8859-1"),"UTF-8");
还有一种对get和post方法都适用的方法,因为不常用就不说了,乱码问题也差不多了,以后有类似的继续补充!