【Java】中文乱码不再乱

     小编总结了一下一些中文乱码的心得,总结一下积累。(最近更新2017年5月9日)

【为什么】

      在页面上输入信息,通过表单等打包提交成request请求发给服务器,jsp在运行时总是被编译成servlet,这期间也会有字符的编译,最终将数据插入数据库中,数据库的字符集等等,这期间的各种字符编码的转换传输等等都会造成乱码。一个J2EE系统的各个组成部分都有各自的字符集编码,如果不做字符集统一,必然会出现乱码。

【解决方案】

       UTF-8无疑是最好的统一选择,UTF-8编码兼容所有语言(具体的编码比较见文尾),唯一比较麻烦的就是需要在数据从输入到进数据库这一系列操作的所有出入管你口都用UTF-8来统一。如下:

1.需要在项目开发和编译时指定字符集UTF-8。Eclipse就直接设置整个项目的属性即可。如下图:


2.在JSP的头部进行声明:

<%@ pagelanguage="java"contentType="text/html;charset=UTF-8"pageEncoding="UTF-8"%>

3.也可以使用过滤器,所有请求都要经过servlet控制分配器,在servlet的filter设置统一。

       详见博客:http://blog.csdn.net/u013036274/article/details/52592818

4.设定数据库连接方式为UTF-8。以mysql连接为例,在连接mysql配置url时:

<?xmlversion="1.0" encoding="UTF-8"?>
<config>
<db-info>
<driver-name>com.mysql.jdbc.Driver</driver-name>       
<url>jdbc:mysql://localhost:3306/drp?characterEncoding=UTF-8</url>
<user-name>root</user-name>
<password>123456</password>
</db-info>
</config>

5.数据库设置为UTF-8,如下图:


6.JSP与页面参数之间的乱码转换

Request.setCharacterEncoding("UTF-8");//从请求中获取参数出现乱码
response.setContentType("text/html;charset=GBK");//将变量输出到页面时出现乱码

    这种情况综合起来还是直接使用过滤器比较合适。

7.Filter设置字符集对get提交方式并不起作用,所以还有一种方式,是配置服务器。一Tomcat为例:Tomcat的配置文件中:.me_tcat/conf/server.xml,如下图:


打开进行如下修改:


8.对中文采用Java.net.URLEncoder.encode()进行编码

 URLEncoder.encode("某中文", "GB18030")

9.其他 

       上面提到的方法应该能解决大部分乱码问题,如果在其他地方还出现乱码,可能需要手动修改代码。

String test=newString(name.getBytes("gbk"),"utf-8");

10.浏览器中文乱码

      最近小编做项目遇到了这样一个问题:通过上文的方法,可以保证谷歌、火狐等浏览器都没问题,但是IE却依然乱码,这是因为IE和火狐对URL的处理不同,浏览器在传输URI时得对URL进行编码,IE默认是以UTF_8来传输的,Firefox是GBK来编码,如果不对中文参数进行处理,中文字符经过各个浏览器以各自的方式传输到服务器后就出现了各种编码方式,而服务器却只能以一种编码方式来对接收到得URL进行解码,这样的话和服务器使用的编码方式一致的浏览器在传中文参数时没问题,不一致的就会有问题。解决方法也很简单,上文介绍中少了一个地方,就是在参数传递之前。我们可以再参数传递之前就进行编码,后台获取参数时再解码即可,并且这种方式可以很好的处理浏览器兼容性问题,这样的话下面的那一段补充液没用了,因为我们根本就不需要知道原来是什么编码。如下:

js代码:

	var url =encodeURI("transport/viewTransitList.do?searchOption="
			+ searchOption + "&searchCondition="
			+ searchCondition);

Controller代码:

		String searchCondition=request.getParameter("searchCondition");
		try {			
			 searchCondition = java.net.URLDecoder.decode(searchCondition, "UTF-8");// 解码
			searchCondition = new String(searchCondition.getBytes("iso-8859-1"), "utf-8");
		
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
		}	

补充:解决Java乱码问题的关键在于在字节与字符的转换过程中,你必须知道原来字节或转换后的字节的编码方式,转换时采用的编码必须与这个编码方式保持一致。但是如何获取字符串的编码格式,实验了几个网上的方案,无果。待续。。。。

【几种编码格式的介绍】----(摘自博客见文尾链接)

       当中国人们得到计算机时,已经没有可以利用的字节状态来表示汉字,况且有6000多个常用汉字需要保存,于是想到把那些ASCII码中127号之后的奇异符号们直接取消掉,规定:一个小于127的字符的意义与原来相同,但两个大于127的字符连在一起时,就表示一个汉字,前面的一个字节(称之为高字节)从0xA1用到0xF7,后面一个字节(低字节)从0xA1到0xFE,这样我们就可以组合出大约7000多个简体汉字了。在这些编码里,我们还把数学符号、罗马希腊的字母、日文的假名们都编进去了,连在ASCII 里本来就有的数字、标点、字母都统统重新编了两个字节长的编码,这就是常说的"全角"字符,而原来在127号以下的那些就叫"半角"字符了。这种汉字方案叫做"GB2312"。GB2312 是对 ASCII 的中文扩展。兼容ASCII。

       但是中国的汉字太多了,我们很快就就发现有许多人的人名没有办法在这里打出来,不得不继续把GB2312没有用到的码位找出来用上。后来还是不够用,于是干脆不再要求低字节一定是127号之后的内码,只要第一个字节是大于127就固定表示这是一个汉字的开始,不管后面跟的是不是扩展字符集里的内容。结果扩展之后的编码方案被称为“GBK” 标准,GBK 包括了 GB2312 的所有内容,同时又增加了近20000个新的汉字(包括繁体字)和符号。

       后来少数民族也要用电脑了,于是我们再扩展,又加了几千个新的少数民族的字,GBK扩成了 GB18030。从此之后,中华民族的文化就可以在计算机时代中传承了。

       中国的程序员们看到这一系列汉字编码的标准是好的,于是通称他们叫做"DBCS"(Double ByteCharecter Set双字节字符集)。在DBCS系列标准里,最大的特点是两字节长的汉字字符和一字节长的英文字符并存于同一套编码方案里,因此他们写的程序为了支持中文处理,必须要注意字串里的每一个字节的值,如果这个值是大于127的,那么就认为一个双字节字符集里的字符出现了。在这种情况下,"一个汉字算两个英文字符!"。然而,在Unicode环境下却并非总是如此。

       在Unicode里,所有的字符被一视同仁。汉字不再使用“两个扩展ASCII”,而是使用“1个Unicode”,注意,现在的汉字是“一个字符”了,于是,拆字、统计字数这些问题也就自然而然的解决了。

       但是,这个世界不是理想的,不可能在一夜之间所有的系统都使用Unicode来处理字符,所以Unicode在诞生之日,就必须考虑一个严峻的问题:和ASCII字符集之间的不兼容问题。

       我们知道,ASCII字符是单个字节的,比如“A”的ASCII是65。而Unicode是双字节的,比如“A”的Unicode是0065,这就造成了一个非常大的问题:以前处理ASCII的那套机制不能被用来处理Unicode了。

       另一个更加严重的问题是,C语言使用'\0'作为字符串结尾,而Unicode里恰恰有很多字符都有一个字节为0,这样一来,C语言的字符串函数将无法正常处理Unicode,除非把世界上所有用C写的程序以及他们所用的函数库全部换掉。

       于是,比Unicode更伟大的东东诞生了,之所以说它更伟大是因为它让Unicode不再存在于纸上,而是真实的存在于我们大家的电脑中。那就是:UTF。

       UTF= UCS TransformationFormat,即UCS转换(传输)格式。它是将Unicode编码规则和计算机的实际编码对应起来的一个规则。现在流行的UTF有2种:UTF-8和UTF-16。这两种都是Unicode的编码实现。

下面两篇博客对这方面介绍的生动风趣,有兴趣可以看一下。

http://blog.csdn.net/guanfengliang1988/article/details/50440197

http://blog.csdn.net/ldanduo/article/details/8203532/

 

 

  • 5
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 46
    评论
评论 46
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值