中文乱码解决方案

<!-- /* Font Definitions */ @font-face {font-family:宋体; panose-1:2 1 6 0 3 1 1 1 1 1; mso-font-alt:SimSun; mso-font-charset:134; mso-generic-font-family:auto; mso-font-pitch:variable; mso-font-signature:3 135135232 16 0 262145 0;} @font-face {font-family:"Cambria Math"; panose-1:2 4 5 3 5 4 6 3 2 4; mso-font-charset:0; mso-generic-font-family:roman; mso-font-pitch:variable; mso-font-signature:-1610611985 1107304683 0 0 159 0;} @font-face {font-family:"Arial Unicode MS"; panose-1:2 11 6 4 2 2 2 2 2 4; mso-font-charset:134; mso-generic-font-family:swiss; mso-font-pitch:variable; mso-font-signature:-134238209 -371195905 63 0 4129279 0;} @font-face {font-family:Calibri; panose-1:2 15 5 2 2 2 4 3 2 4; mso-font-charset:0; mso-generic-font-family:swiss; mso-font-pitch:variable; mso-font-signature:-1610611985 1073750139 0 0 159 0;} @font-face {font-family:"/@宋体"; panose-1:2 1 6 0 3 1 1 1 1 1; mso-font-charset:134; mso-generic-font-family:auto; mso-font-pitch:variable; mso-font-signature:3 135135232 16 0 262145 0;} @font-face {font-family:"/@Arial Unicode MS"; panose-1:2 11 6 4 2 2 2 2 2 4; mso-font-charset:134; mso-generic-font-family:swiss; mso-font-pitch:variable; mso-font-signature:-134238209 -371195905 63 0 4129279 0;} /* Style Definitions */ p.MsoNormal, li.MsoNormal, div.MsoNormal {mso-style-unhide:no; mso-style-qformat:yes; mso-style-parent:""; margin:0cm; margin-bottom:.0001pt; text-align:justify; text-justify:inter-ideograph; mso-pagination:none; font-size:10.5pt; mso-bidi-font-size:11.0pt; font-family:"Calibri","sans-serif"; mso-fareast-font-family:宋体; mso-bidi-font-family:"Times New Roman"; mso-font-kerning:1.0pt;} .MsoChpDefault {mso-style-type:export-only; mso-default-props:yes; font-size:10.0pt; mso-ansi-font-size:10.0pt; mso-bidi-font-size:10.0pt; mso-ascii-font-family:Calibri; mso-fareast-font-family:宋体; mso-hansi-font-family:Calibri; mso-font-kerning:0pt;} /* Page Definitions */ @page {mso-page-border-surround-header:no; mso-page-border-surround-footer:no;} @page Section1 {size:595.3pt 841.9pt; margin:72.0pt 90.0pt 72.0pt 90.0pt; mso-header-margin:42.55pt; mso-footer-margin:49.6pt; mso-paper-source:0; layout-grid:15.6pt;} div.Section1 {page:Section1;} /* List Definitions */ @list l0 {mso-list-id:1608925745; mso-list-template-ids:629205626;} @list l0:level1 {mso-level-tab-stop:36.0pt; mso-level-number-position:left; text-indent:-18.0pt;} @list l1 {mso-list-id:1748769821; mso-list-template-ids:-925629664;} @list l1:level1 {mso-level-tab-stop:36.0pt; mso-level-number-position:left; text-indent:-18.0pt;} @list l2 {mso-list-id:1870676537; mso-list-template-ids:-1979043108;} @list l2:level1 {mso-level-tab-stop:36.0pt; mso-level-number-position:left; text-indent:-18.0pt;} @list l3 {mso-list-id:1976569749; mso-list-template-ids:-268377040;} @list l3:level1 {mso-level-tab-stop:36.0pt; mso-level-number-position:left; text-indent:-18.0pt;} ol {margin-bottom:0cm;} ul {margin-bottom:0cm;} -->

IE6 的“ 以UTF-8 发送URL” 选项设置对请求页面字符编码有影响吗?

关键字: 字符编码

      最近又碰到了中文乱码问题,这里我没有把数据库牵扯进来,先说下我的环境,servlet 容器使用Tomcat6.0 ,浏览器FireFox3.0IE6 ,涉及字符编码设置的地方我的思路就是编码的地方都统一使用UTF-8 ,具体配置如下:

1. 所有页面的charset 设置为UTF-8

2.Tomcat URIEncoding 默认是ISO-8859-1 ,而我设置为UTF-8 ,主要是想解决中文命名的文件以及请求以get 方式提交有可能出现的乱码问题。

3. 添加过滤器,调用request.setCharacterEncoding("utf-8") 方法将request 的字符集设定为utf-8 ,解决请求以post 方式提交的乱码问题。

其实这样的设置貌似是不会再出现乱码问题了,不过,问题依旧来了 http://battlehawk.javaeye.com/images/smiles/icon_cry.gif ,如果我在浏览器的地址栏中输入中文参数提交,返回的页面却出现了乱码。真搞不明白到底是哪里出了问题!说起来对中文乱码的问题一直是一支半解,出现乱码了,网上搜罗了一大堆资料,按照网上的配置,问题到是解决了,不过原理却搞的很模糊,一个请求发送到服务器,服务器业务逻辑处理后返回一个页面,这中间涉及的字符集转换,编码,解码过程一概不清楚。这次,折腾了半天,总算是更进一步了解了字符编码问题,这里做个总结。

先看我的总结, 有不对的地方欢迎批评。

首先我们看下,一个请求响应的流程

 

浏览器 IE/FireFox -------->Servlet 容器-----------------> 显示页面

       编码           使用容器的URIEncoding 转码              解码

我把用户发送请求方式不同引起的中文问题划分了四种类型:

1 、表单的get 提交

2 、表单的post 提交

3 、页面链接传递中文参数

4 、地址栏中参数直接输入中文提交

 

1. 首先我们看表单get 方式提交

      浏览器根据页面的charset 编码方式对页面进行编码,然后提交至服务器,首先进入对应的字符编码过滤器( 如果有的话) ,不过Tomcat6.0 对于get 提交方式采用的是server.xml 文件中的URIEncoding 编码方式,而并不会采用过滤器中设置的编码,那么根据我的环境设置,jsp 页面都使用UTF-8 的编码,Servlet 容器的URIEncoding 也设置为UTF-8 ,则servlet 不用进行转码即可正确解码,获得正常的中文字符串。那么,响应页面的中文因为页面的统一编码(UTF-8) 自然也会正常显示。当然,如果我们TomcatURIEncoding 设置为其他非UTF-8 的编码方式时,页面的内容进入Tomcat 解析时,因为Tomcat 和页面的编码不统一,就需要转码。例如,如果我们采用Tomcat 默认的ISO-8859-1 ,那么当我们使用request.getParameter("yourVariable ") 获取表单参数值时其实Servlet 就进行了转码,它会以容器编码方式进行解码,这个过程如下:

UTF-8( 编码)-->ISO-58859-1( 解码)

这个过程也相当于我们使用如下的语句

Java 代码 复制代码

  1. new String( 变量值.getBytes("UTF-8"),"ISO-8859-1");  

new String( 变量值.getBytes("UTF-8"),"ISO-8859-1");

根据API 的解释,先将变量值以UTF-8 字符集编码转换为字节序列,再以ISO-8859-1 字符集解码字节数组,构造出新的字符串对象。

等价于以下方式:

Java 代码 复制代码

  1. String code = " 编码";   
  2. code = URLEncoder.encode(code,"UTF-8");   
  3. code = URLDecoder.decode(code,"ISO-8858-1");  

String code = " 编码";

code = URLEncoder.encode(code,"UTF-8");

code = URLDecoder.decode(code,"ISO-8858-1");

 

例如表单的username 属性以字符串" 编辑" 提交,那么进入容器后,FormBean 中的这个变量会乱码,request.getParameter(username) 一样的效果,s1 就是request 返回的结果,下面是内存快照。
http://battlehawk.javaeye.com/upload/attachment/62605/047b7060-fcb4-33c0-9b89-e00b3267b5c5.jpg

不过即使这样,我们依然可以使用不恰当的方法显示正常的中文,即逆向转码,例如上面的乱码,我们可以通过ISO8859-1-->UTF-8 这种方式还原我们提交时的中文。以下是GBKUTF-8ISO-8859-1 三者之间互相转换的内存快照:
http://battlehawk.javaeye.com/upload/attachment/62609/acf55e49-b1d8-30dd-a8b3-ff97e2281628.jpg

  我们可以看到,偶数汉字可以在UTF-8GBK 两者中互相转换,而奇数个汉字则不能。综上看来,貌似TomcatURIEncoding 设置为UTF-8 是最好的解决办法,不过这样的设置依然无法解决上面我所说的第三、第四种情况。大家继续向下看。( 这里有一点我不确定,就是页面提交至Servlet 容器时,是以页面的charset 方式编码后直接进入容器,还是以charset 转码为ISO-8859-1 方式进入,大家有什么见解?)
2.
表单的post 提交

对于这种方式的请求,request.setCharacterEncoding(" 一般来自于web.xml 中过滤器设置的参数") 方法进行编码设置将会产生作用,struts 的表单提交方式默认为post 方式,那么按照上面我的环境设置,页面,容器,都采用UTF-8 编码方式,就不会产生中文乱码问题。
3.
页面链接中传递中文参数

我虚拟一个这样的场景,请求页面中有如下代码

Html 代码 复制代码

  1. < %   
  2. String username  = " 编辑" ;   
  3. %>   
  4. <a  href ="hello.do?username=<%=username%>" > 页面中链接传递中文</a>   

<%

String username = " 编辑";

%>

<a href="hello.do?username=<%=username%>"> 页面中链接传递中文</a>

对于这种方式,我们需要先将参数使用统一的编码方式编码,将编码后的字符放入链接,这里我对参数以UTF-8 方式编码,如下

Java 代码 复制代码

  1. <%   
  2. String username = java.net.URLEncoder.encode(" 编辑","UTF-8");   
  3. %>  

<%

String username = java.net.URLEncoder.encode(" 编辑","UTF-8");

%>

那么这样我们也不会产生中文乱码问题

4. 地址栏中参数直接输入中文提交

例如浏览器地址栏中输入"http://localhost:8080/helloapp.do?username= 编辑" 提交,对于这种方式,浏览器不会采用页面的charset 方式对URL 中的中文进行编码后提交至服务器(IE,FireFox 都一样) ,而是采用系统的GBK 转码为ISO-8859-1 之后提交至Servlet 容器,那么,如果对于前三种方式我们所做的设置,在这里就有问题了,因为进入容器时中文进行了GBKISO-8859-1 的转码,而之前我们的Servlet 容器URIEncoding 设置为UTF-8 ,当我们使用request.getParameter("username") 时,相当于又进行了这样的流程GBK-->ISO-8859-1-->UTF-8 ,按照以上我们使用的测试中文, 编辑 ,使用request.getParameter("username") 则会得到这样的结果 �༭ ,下图是进行转码的内存快照:


http://battlehawk.javaeye.com/upload/attachment/62633/31d0defa-d861-3990-9f24-5702f2e58e4b.jpg

我们可以看到

编辑 经过从GBK-->ISO-8859-1-->UTF-8 的过程后得到的就是 �༭ 这样的结果,这里我们还会想到那进行2 次逆向转码看看,不过可惜的是,结果为 锟洁辑 。对于这种情况,我们的解决办法就是,TomcatURIEncoding 采用默认的ISO-8859-1 字符集,那么我们可以在程序中通过ISO-8859-1-->GBK 这样不恰当的逆向转码方式得到正常的中文 编辑 ,但这样的结果是,我们get 请求方式的中文处理解决办法就需要改变。如,在我的环境下就需要进行ISO-8859-1-->UTF-8 的转码,挺不爽。

 

综上,对于乱码问题,前三种方式是一般用户的请求方式,第四种属于非正常途径的请求方式,对于这种方式产生的问题我认为无法很好的解决,也不需要解决。我看到javaeye 对于这样的情况就没有处理,不知道大家在自己的项目中是如何处理的?我的实验是,IE6 的设置会影响应用路径的编码方式,例如地址栏中请求一个中文JSP 页面,如:http://localhost:8080/helloapp/ 编辑.jspIE 默认是勾选"UTF-8 发送URL" 项的,那么按照我上面总结的处理方式,这个请求可以正常显示页面,如图:
http://battlehawk.javaeye.com/upload/attachment/62772/4411bf0f-3e00-35bb-9f86-fcbf70e26499.jpg

如果取消IE 的这个选项,那么浏览器会以GBK 编码应用路径的中文,得到的结果如图:
http://battlehawk.javaeye.com/upload/attachment/62775/b867ff31-5d43-3686-a8de-ebe44fae54f4.jpg

按照我上面的设置,这里如果将TomcatURIEncoding 设置为GBK ,则也可以正常显示页面。对于FireFox3.0 ,则是以UTF-8 编码。

最后,回到我的题目,向大家讨教下,IE6UTF-8 发送URL” 选项设置对请求页面字符编码有影响吗?欢迎讨论!

 

我的测试代码共享给大家:), 使用的是struts1.2strutsjar 包,大家可以去apache 下载。

 

这里推荐个链接,有兴趣的可以深入了解更多字符集、编码的问题。

http://hideto.javaeye.com/blog/97803

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值