虽然以前就知道编码问题,但是一直没有遇到问题,以前用asp.net和php的时候,感觉很自然地写程序,没怎么特别处理编码问题,这回改用java写,真心被恶心到了。
进行了一番查阅学习后,终于搞明白了一些东西。
中文乱码出现的原因,是因为tomcat和jsp的默认编码是ISO-8859-1,不支持中文,支持中文的常用的有三种编码,gb2312,gbk,utf-8,所以需要指定用这三种中的一种。web程序总分为请求和响应,这个过程中的内容就是先被编码然后再解码,如果不一致的话,就会导致出现中文乱码的问题。
首先我要说下我的编码选择,再查阅了大量有关gb2312,gbk,utf-8的资料后,我还是选择了utf-8,以下是我的理由,全是网上查到的资料,如有误,还望指出:
1、gbk是gb2312的扩展,完全包含gb2312,gbk包含所有汉字字符的编码。而且eclipse里的字符编码居然默认是gbk,windows平台(7和以前的,不知道win8是什么情况)默认也是gbk,虽然gbk不是国家标准,但是国内用得最广的中文字符编码方式。所以这两者中选一个,毫无疑问,选择gbk。
2、utf-8和gbk编码机制不一样,gbk不管英文中文全部用两个字符进行编码,utf-8则是对于英文字符用一个字符,对非英文字符用三个字符。看到网上一堆人讨论导致的页面大小问题,看多了给我的感觉是没啥区别,如果全是英文毫无疑问使用utf-8的页面会很小,国内的中文网站其实一个页面里的大部分也是html代码,很少有中文远远多于英文字符的,除非那种页面特别长的阅读类网站,不过大部分也有翻页机制吧,所以大小问题不怎么重要。
3、gbk是国内一种机制,utf-8是国际标准。就是说试用utf-8编写的网站,外国人用浏览器无需下载解码包就能正确显示内容,用gbk的不使用解码包则显示乱码。
4、linux默认支持utf-8,而不支持gbk,需要额外工作才能让其支持gbk。
5、utf-8是国际标准,也是未来的主流,使用utf-8可以省很多事,大部分企业内部也是使用utf-8编码。sina、baidu等大公司大部分gbk的站点是历史原因,新项目都是用utf-8。(看到的资料)
6、据说gbk很容易导致jquery等js框架出现乱码问题,而utf-8不会。
好了,也不多说了,根据这几点我还是选择了utf-8,不过网上有大牛说有大公司还有选择gb2312的,因为那个访问中文网站速度更快,我有点相信这个的,因为utf-8是国际编码机制,gbk是特定针对中文的,一般来说通用性好的效率会差点。不过也就百度 sina这种超大型的站点才需要考虑这些技术细节,对于普通站点,为了少遇到问题,还是选择utf-8为好。
再说说乱码问题,乱码一般是在对参数编码解码时产生的。web中的传参方法就是两种,post方法或者get方法。
首先我们要设置好页面编码。jsp页面有三个地方可以设置编码方式。
<%@ page language="java" pageEncoding="UTF-8"%>
<%@ page contentType="text/html;charset=iso8859-1"%>
<html>
<head>
<title>中文编码问题</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
</head>
</head>
<body>
中文编码问题
</body>
</html>
pageEncoding是jsp文件的存储格式,Eclipse会根据这个编码格式保存文件,并编译jsp文件,包括里面的汉字。contentType是解码格式,存成utf-8的文件用iso8859-1解码,肯定会出现乱码。一般来说第二行是不写的,设置了pageEncoding后,contentType就一样了,如果需要单独设置,则需都写出来。都不写,就都是默认的iso8859-1。第三处编码为控制浏览器的解码方式。如果前面的解码都一致并且无误的话,这个编码格式没有关系。有的网页出现乱码,就是因为浏览器不能确定使用哪种编码格式。因为页面有时候会嵌入页面,导致浏览器混淆了编码格式,出现了乱码。
使用get传参出现的乱码问题解决:
1、String str = new String(request.getParameter("something").getBytes("ISO-8859-1"),"utf-8") 这属于直接转码,都这么写有点麻烦,不推荐
2、修改tomcat等web容器的配置,设置好了之后可以不用管get传参的问题了,推荐使用。Get走的是url提交,而在进入url之前已经进行了iso8859-1的编码处理。要想影响这个编码则需要在server.xml的Connector节点增加useBodyEncodingForURI="true"属性配置,即可控制tomcat对get方式的汉字编码方式,上面这个属性控制get提交也是用request.setCharacterEncoding("UTF-8")所设置的编码格式进行编码。所以自动编码为utf-8,接受页面正常接受就可以了。
<Connector port="8099" protocol="HTTP/1.1" connectionTimeout="20000" redirectPort="8443" URIEncoding="utf-8" /> <Connector port="8000" protocol="HTTP/1.1" connectionTimeout="20000" redirectPort="8443" URIEncoding="utf-8" />
使用post传参出现乱码问题解决:
1、同上面第一种方法
2、使用request.getParameter取参数之前先设置编码格式request.setCharacterEncoding("utf-8"),指定后可以通过getParameter()则直接获得正确的字符串,如果不指定,则默认使用iso8859-1编码。值得注意的是在执行setCharacterEncoding()之前,不能执行任何getParameter()。而且,该指定只对POST方法有效,对GET方法无效!!!。分析原因,应该是在执行第一个getParameter()的时候,java将会按照编码分析所有的提交内容,而后续的getParameter()不再进行分析,所以setCharacterEncoding()无效。而对于GET方法提交表单是,提交的内容在URL中,一开始就已经按照编码分析提交内容,setCharacterEncoding()自然就无效。
3、为了避免每页都要写request.setCharacterEncoding("UTF-8"),建议使用过滤器对所有jsp进行编码处理。这个网上有很多例子。请大家自己查阅。
Java代码关于url请求,接受参数的乱码:
url的编码格式,取决于上面所说的URIEncoding=”UTF-8”。如果设定了这个编码格式,则意味着所有到url的汉字参数,都必须进行编码才可以。否则得到的汉字参数值都是乱码,例如一个链接:response.sendDerect("/a.jsp?school=北科大");而在a.jsp里面直接使用 String school= request.getParameter("school");得到的就是乱码。因为规定了必须是utf-8才可以,所以,这个转向应该这样写:
response.sendRedirect("a.jsp?school="+java.net.URLEncoder.encode("北科大","utf-8"));