web乱码解决

前言: 我之前对于乱码的态度就是上网上搜解决办法,找到一个就实验一个,直到找到了能解决的办法就行了,也不去仔细研究,结果就是每次出现乱码,我都不知怎么解决,有重复以前的步骤,

找到一个实验一个。 这样的学习态度是很不可取的,不仅学不到东西,而且极大的降低了自己的学习热情,现在我要彻底解决它。

编码的基础知识

编码和解码: 首先明确码是什么? 码是字节数组,所以编码(encode)就是从字符串得到字节数组,而解码(decode)就是从字节数组得到字符串,在编码和解码过程中需要一个标准,其实就是

字节与字符之间的对应关系,这个就是字符集。在java中String类有两个常用的方法进行编码和解码

getBytes :例如“中”.getBytes(“字符集”),根据指定的字符集进行编码

String(bytes[],”字符集”):根据自定的字符集对字节数组进行解码

另外还有一个概念是为URI编码和URI解码,不过URI编码和解码不是字符串和字节流之间的转换,而是由一个字符串表示另一个字符串,例如:

“中”的UTF-8 URI编码为 %E4%B8%AD

字符串%E4%B8%AD根据UTF-8进行URI解码为字符“中”

可以看出来,URI编码就是将一个字符串用%+对应字符集的编码组织的字符串来表示的,java中uri编码和uri解码的方法

URLEncoder.encode("傻逼", "utf-8")

URLDecoder.decode("%e5%82%bb%e9%80%bc", "gbk");

另外在js中用于uri编码的常用方法是:encodeURIComponent() 函数 与 encodeURI() 函数,关于他们的区别参见另一篇笔记。

出现乱码的原因:

web是基于请求响应的,当我们通过浏览器向服务器发送请求时会携带请求参数,而参数是需要转换为字节流来在网络上传播的,也就是编码,所以浏览器就

会根据一定的原则来确定根据某个字符集来对请求参数编码,当请求参数传递到服务器后,服务器又会根据某种原则选择出响应的字符集对浏览器传递来的字节流

进行解码为字符串。了解了这个过程我们就发现问题了,如果这两次编码和解码所依据的字符集不同,那么自然就会出现乱码了,这也就是乱码出现的本质。

首先来看看浏览器是怎样来编码的:

向服务器提交请求一般有三种方式: 1.提交表单 2.超链接 3.ajax

1. 提交表单 又分为post和get两种方式

采用post方法时浏览器会将表单中的字符串,采用页面的字符集编码为字节流发送到服务器,

采用get方法时,浏览器首先会将表单中的值通过页面的字符集进行URI编码后拼接到action的URL后面发送到应用服务器

所以可以知道无论post还是get,编码方式都是有页面上指定的字符集确定的。

2.ajax

这个是比较蛋疼的,因为页面上设置的编码方式对于ajax不起作用,我在做光纤地图的项目中就吃了亏,而是总是按照utf-8来编码的

3.超链接

对于超链接,如果携带中文,浏览器会进行uri编码,但是编码方式和客户端的环境有关。所以为了避免浏览器进行不确定的URI编码,需要在程序中将中文进行URI编码后在放到URL中。

下面就是看服务器端的解码方式了:

下面是针对tomcat而言:

对于post方式提交(包括表单和ajax 的post),编码方式是由request.setCharacterEncoding()方法来决定的,在servlet中应该在getParameter方法之前调用这个方法才有作用。

在struts中是通过<constant name="struts.i18n.encoding" value="gbk"></constant>这个常量来设置的。

对于get和超连接的情况,下面是参考别人的说法:

tomcat5.5中getParameter获取get方法或超链接传过来的参数时默认会用ISO8859-1进行解码,例如浏览器发送UTF-8的编码的请求,tomcat5.5的getParameter使用ISO8859-1解码,这时的结果是错的,如果要获得正确的值,需要在tomcat5.5的getParameter的时候采用UTF-8进行解码,通过设置URIEncoding="UTF-8"或者useBodyEncodingForURI="true",就能让tomcat在的getParameter时采用UTF-8解码(useBodyEncodingForURI="true"表示解码的字符集采用与页面编码相同的字符集),对于超链接的情况,在服务器端还应该对开始uri编码的参数进行uri解码。

通过上面的分析,我们可以发现只要编码和解码的字符集设置为一样的,就不会出现乱码,所以总结为:

1. 设置请求页面的编码,pageEncoding="GBK"

2.对于超连接采用encodeURI("中国","GBK")来进行uri转码。

3.在服务器端设置request.setCharacterEncoding()或者<constant name="struts.i18n.encoding" value="gbk"></constant>

4.在tomcat中设置URIEncoding="UTF-8"或者useBodyEncodingForURI="true"

到此为止,我们还剩下一个问题就是ajax时的编码问题,如果我们采用的统一编码为utf-8,那么ajax是没有什么问题的,但是如果统一编码为gbk,就有问题了,因为ajax在浏览器端总是

通过utf-8进行编码的,而在服务器端我们设置的统一编码为gbk,自然就出现乱码了,其实我们可以分析一下就是

字符串---》uft-8编码---》gbk解码 造成的乱码,我们先看看这种思路:可以逆向转换回去,首先使用gbk编码,然后在使用utf-8解码,就比如

        byte[] buf = "中国".getBytes("utf-8");//使用uft-8编码
        String str1 = new String(buf, "gbk");//使用gbk解码
        System.out.println(str1);//打印出乱码
        byte[] buf2 = str1.getBytes("gbk");//使用gbk编码
        String str2 = new String(buf2, "utf-8");//使用utf-8解码
        System.out.println(str2);//打印出中国

 这种方法看似很合理,其实是错误的。 因为如果出现乱码了,未必能由乱码字符串编码会原来的字节流,比如上面的例子,如果不是“中国”,而是“中”,或者“中国人”,就不能得到正确的结果。

所以正在可行的就是下面这种做法,

把中文字符串uri编码先变为ascii字符串,这样无论使用何种编码字符集都可以再服务器端得到这个新生成的ascii字符串,然后自己在对这个ascii字符串按照在开始时uri编码的

字符集来uri解码,就可以保证得到正确的中文参数了。

还有一种解决办法就是想对待超连接一样,在客户端发送之前对参数进行一次uri编码,让参数成为ascii字符串,这样

就可以利用任何字符集编码解码ascii字符串得到相同结果的原理,当服务器端使用不同字符集解码后仍然得到原参数uri编码得到的那个ascii字符串, 最后自己在进行一次uri解码就可以了。

        String a = URLEncoder.encode("说说","utf-8");//模拟在客户端发送之前自己先编码一次,将参数变为ascii字符串

        byte[] buf = a.getBytes("utf-8");;//模拟浏览器对参数编码

        String b = new String(buf, "gbk");//模拟服务器对参数解码

        String c = URLDecoder.decode(b, "utf-8");//最后自己在把参数解码

        System.out.println(c);//打印 “说说”

最后说一下为什么我们无须使用spring的编码过滤器,在spring编码过滤器中有:

public void prepare(HttpServletRequest request, HttpServletResponse response) {
        String encoding = null;
        if (defaultEncoding != null) {
            encoding = defaultEncoding;
        }  

       //省略了一些代码  

        if (encoding != null) {
            try {
                request.setCharacterEncoding(encoding);//设置了字符集编码
            } catch (Exception e) {
                LOG.error("Error setting character encoding to ‘" + encoding + "‘ - ignoring.", e);
            }
        }
    //省略了一些代码
    }  

我们可以看到其实它不过也就是调用了

request.setCharacterEncoding(encoding);而已,和我们自己做的没有什么太大区别。

设置浏览器的页面编码

服务器向浏览器发送的也是经过编码成字节流在网络上传输,浏览器接收到字节流之后使用指定的字符集解码成字符串再进行展现,如果这两个环节的字符集不一致也会导致乱码的问题,

例如静态HTML文件或jsp中都是以UTF-8保存的,则需要告诉浏览器用UTF-8来进行解码,

  • 如果是jsp可以通过<%@ page contentType="text/html; charset=UTF-8" language="java" %>来进行设置,
  • 静态文件可以通过 <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/> 进行设置,
  • 如果在servlet中直接进行输出,可以通过response.setCharacterEncoding("UTF-8"),setContentType("text/html;charset=UTF-8"),setHeader("Content-Type","text/html;charset=UTF-8")进行设置,

这些操作都相当于在response的头部增加"Content-Type:text/html;charset=UTF-8"信息,

header中的编码信息的优先级要高于html的meta标签,也就是说如果serlvet中设置了setContentType("text/html;charset=UTF-8"),jsp设置了<meta http-equiv="Content-Type" content="text/html; charset=GBK"/>则浏览器会按照UTF-8字符集进行解码,

时间: 2024-08-13 04:49:20

web乱码解决的相关文章

Web乱码解决办法

在项目中偶尔会遇到jsp传到后台出现中文乱码而不知所措.下面将讲解出现中文乱码的几种情况. jsp页面没有设置编码格式, 后台没有在web.xml中配置字符编码过滤器, 在ajax提交的时候用get提交, 数据库连接的时候也可以试着加上字符编码, 所有的前台和后台字符编码必须一致. JSP页面没有设置编码格式 JSP中“charset”与“pageEncoding”的区别 pageEncoding:表示页面编码,是设置JSP页面源代码的字符编码格式,如果该项的值是utf-8,则JSP源代码里不能

玩转web之ajax(一)---使用表单的serialize()方法中文乱码解决

有时候我们需要使用ajax提交去提交form的值,这样就需要使用serialize()去获取form的值,但这样获取的值如果有中文,会乱码,原因和解决方法如下: 原因:.serialize()自动调用了encodeURIComponent方法将数据编码了 解决方法:调用decodeURIComponent(XXX,true);将数据解码 如: var data=$('#addf').serialize(); data= decodeURIComponent(data,true); 玩转web之a

web页面导出到Excel乱码解决

引言: 前几天 在做web项目的时候 需要导出页面上的数据 到Excel里面 但有的时候出现乱码(有de时候不出现 很奇怪) 原来的代码是这样的: HttpContext.Current.Response.Clear(); HttpContext.Current.Response.AddHeader("content-disposition", "attachment;filename=FileName.xls"); HttpContext.Current.Resp

Zabbix4.0 Web管理界面中文乱码解决方法(转)

Zabbix安装好之后,监控图形页面出现字符集乱码 解决方法:1.复制本地电脑C:\Windows\Fonts\simkai.ttf(楷体)上传到zabbix服务器网站目录的fonts目录下 2.zabbix网站目录fonts目录查找如下:[[email protected] ~]# whereis zabbixzabbix: /usr/lib/zabbix /etc/zabbix /usr/share/zabbix[[email protected] ~]# cd /usr/share/zab

asp.net url址址中中文汉字参数传递乱码解决方法

中文乱码是网站开发中会常碰到的问题,今天我们来讲一下关于url址址中中文汉字参数传递乱码解决方法,有需要的朋友可以参考下.在cs文件里传参的时候用UrlEncode: Response.Redirect("B.asp教程x?Name="+Server.UrlEncode(Name)); 接参的时候用UrlDecode: Response.Write(Server.UrlDecode(Request.QueryString["Name"])); 脚本儿里传参的时候用e

PHP中文乱码解决办法

一.         首先是PHP网页的编码 1.     php文件本身的编码与网页的编码应匹配 a.     如果欲使用gb2312编码,那么php要输出头:header("Content-Type: text/html; charset=gb2312"),静态页面添加<meta http-equiv="Content-Type" content="text/html; charset=gb2312">,所有文件的编码格式为ANS

Spring MVC传值乱码解决

在web.xml中进行配置,加入以下代码: 1 <!-- 乱码解决 --> 2 <filter> 3 <filter-name>characterEncodingFilter</filter-name> 4 <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class> 5 <init-param> 6 <para

jsp中文乱码解决办法

一.JSP页面显示乱码 二.表单提交中文时出现乱码 三.数据库连接 大家在JSP的开发过程中,经常出现中文乱码的问题,可能一至困扰着您,我现在把我在JSP开发中遇到 的中文乱码的问题及解决办法写出来供大家参考. 一.JSP页面显示乱码下面的显示页面(display.jsp)就出现乱码: <html>< head>< title>JSP的中文处理</title> < meta http-equiv="Content-Type" con

九种乱码解决办法(非原创)

九种解决乱码方法总结2007-09-13 14:01:08 分类: IT综合技术 对于Java由于默认的编码方式是 UNICODE,所以用中文也易出问题,常见的解决是String s2 = new String(s1.getBytes(“ISO-8859-1”),”GBK”);前三种方法是我比较常用的方法,别人的经验告诉我:通常get方法通过改server.xml解决,post方法通过过滤器或者设置字符集解决,呵呵,不知道是否可行! 1.utf8解决JSP中文乱码问题 一般说来在每个页面的开始处