IE6 发送奇数个汉字出现的BUG机器解决之道

  一 IE6与IE7向服务器传递参数的问题

    表现:ie7正常,ie6 参数就会出现中文接受信息错误(长度为奇数时最后一个字符会出现乱码)

    原因:ie7支持UTF8编码,但是ie6支持不好。

    解决方法:

    1、用post发送,这个方法当然不出错了,但是,有时候必须用传参的方法,那就没则了,用第二个方法。

    2、习惯把中文字符串显示长度设置为偶数 ——全是汉字时,无论奇数还是偶数,都无乱码;
如果是英文中文混合,并且英文字符数是奇数时,就会出现最后有一个?号;
如果是英文中文混合,并且英文字符数是偶数时,无乱码。

    解决方案:在业务方法里进行判断,如果输入的字符个数为奇数,则给其拼接上一个全角的空格,如果是半角的空格,也会有乱码问题;或者,在js里面利用escape()函数来解决:

    <script>

        url = "object.html?name=" + escape("张三丰");

    </script>

    原理:见下文——在windows操作系统上使用IE作为浏览器时,常常会发生这样的问题:在浏览使用UTF-8编码的网页时,浏览器无法自动侦测(即没有设定“自动选择”编码格式时)该页面所用的编码,即——当网页标题是中文时,可能会出现打不开网页的情况;即使网页已经声明过编码格式:<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />也会造成某些含有中文UTF-8编码的页面产生空白输出。

    如果使用的是Mozilla、Mozilla Firefox、Sarafi的浏览器这不会造成这个问题。这是由于IE解析网页编码时以HTML内的标签优先,而后才是HTTP header内的讯息;而mozilla系列的浏览器则刚刚相反。

    由于UTF-8为3个字节表示一个汉子,而普通的GB2312或BIG5是两个,因此,页面输出时,由于上述原因,使浏览器解析、输出<title></title>的内容时,如果在</title>前有奇数个全角字符时,IE把UTF-8当作两个字节解析时出现半个汉字的情况,这时该半个汉字会和</title>的<结合成一个乱码字,导致IE无法读完<title>部分,使整个页面为空百输出。而这个时候如果察看源文件的话,会发现实际上整个叶面全部已经输出了。

    因此最简单的解决办法是再网页文件的<head></head>标签中一定要把字符定义<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> 放在<title></title>之前。

 

 

    下面再通过一篇文章来全面说明一下web开发中的编码转换过程及其解决之道:

    

一个请求响应的流程:

浏览器 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)自然也会正常显示。当然,如果我们Tomcat的URIEncoding设置为其他非 UTF-8的编码方式时,页面的内容进入Tomcat解析时,因为Tomcat和页面的编码不统一,就需要转码。例如,如果我们采用Tomcat默认的 ISO-8859-1,那么当我们使用request.getParameter("yourVariable ")获取表单参数值时其实Servlet就进行了转码,方式为UTF-8-->ISO-58859-1(我的页面charset都是UTF-8),类似于这样

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

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

 例如表单的username属性以字符串"编辑"提交,那么进入容器后,FormBean中的这个变量会乱码,request.getParameter(username)一样的效果,s1就是request返回的结果,下面是内存快照。

不过即使这样,我们依然可以使用不恰当的方法显示正常的中文,即逆向转码,例如上面的乱码,我们可以通过ISO8859-1-->UTF-8这种方式还原我们提交时的中文。以下是GBK,UTF-8,ISO-8859-1三者之间互相转换的内存快照:

 我们可以看到,偶数汉字可以在UTF-8,GBK两者中互相转换,而奇数个汉字则不能。综上看来,貌似Tomcat的URIEncoding设置为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容器,那么,如果对于前三种方式我们所做的设置,在这里就有问题了,因为进入容器时中文进行了GBK至ISO- 8859-1的转码,而之前我们的Servlet容器URIEncoding设置为UTF-8,当我们使用 request.getParameter("username")时,相当于又进行了这样的流程GBK-->ISO- 8859-1-->UTF-8,按照以上我们使用的测试中文,“编辑”,使用request.getParameter("username")则会得到这样的结果�༭,下图是进行转码的内存快照:


我们可以看到

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

 

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

如果取消IE的这个选项,那么浏览器会以GBK编码应用路径的中文,得到的结果如图:

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

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

 

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

 

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

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

posted @ 2009-11-12 15:54  弹着钢琴设计  阅读(1038)  评论(0编辑  收藏  举报