java字符集

 

java/jsp的字符集是老问题了,这里谈一下我的理解。

我们简单点拿一个"中"字来说,它的gb2312编码十六进制字符串是d6 d0(下面均以十六进制表示),ASCII码对应gb2312不变,所以中文在gb2312中是双字节,ASCII是单字节。

那么当java把d6 d0理解为gb2312编码时它对应的字符集编码是

unicode: 4e 2d

utf-8:   e4 b8 ad

iso:     3f

因为单字节iso对应unicode双字节,而4e 2d在iso-map-unicode表中找不到,故对应单字节3f,打印出来即“?”

当java把d6 d0理解为iso8859-1编码时它对应的字符集编码是

unicode: 00 d6 00 d0

utf-8:   c3 96 c3 90

gb2312:  3f 3f

因为00 d6和00 d0在gb2312-map-unicode表中找不到,故对应两个3f,打印出来即“??”

下面是一段名词介绍。

jsp-pageEncoding:指定jspc来解释jsp成servlet时使用的字符集,这个属性会影响到页面中写定的中文字符的输出结果。

jsp-charset:指定jsp的out输出时的字符集,out的输出函数将会使用该字符集转换内存中数据。

jspc-memory(unicode):内存中都是unicode。

servlet/class(utf-8):硬盘上的servlet源文件和编译后的class文件,都是utf-8。

out:会根据jcs来转换内存中数据。

brower(iso8859-1):客户端浏览器使用iso8859-1字符集来解析服务器返回的数据,默认是jsp-charset。

brower(gb2312):客户端浏览器使用gb2312字符集来解析服务器返回的数据,默认是jsp-charset。

来看看服务器端页面中直接输出"中"字的情形,如

在中文windowns xp(默认gb2312编码)下用ultraEdit打开一个jsp敲入out.println("中");并不做编码转换,则用十六进制显示可以看到"中"对应d6 d0。

第一种情况

<%@ page pageEncoding="iso8859-1" %>
<%@ page contentType="text/html;charset=iso8859-1" %>

读jsp到内存中(unicode):00 d6 00 d0

servlet/class(utf-8):c3 96 c3 90

读class到内存中(unicode):00 d6 00 d0

out(iso8859-1):d6 d0

浏览器(iso8859-1):⊙ ⊙

浏览器(gb2312):中

上面恰巧的是d6 d0如果当作iso8859-1输入又再当作iso8859-1输出则正好又变回d6 d0,客户端用gb2312显示正好是"中"。

第二种情况

<%@ page pageEncoding="iso8859-1" %>
<%@ page contentType="text/html;charset=gb2312" %>

读jsp到内存中(unicode):00 d6 00 d0

servlet/class(utf-8):c3 96 c3 90

读class到内存中(unicode):00 d6 00 d0

out(gb2312):3f 3f

浏览器(iso8859-1):? ?

浏览器(gb2312):? ?

第三种情况

<%@ page pageEncoding="gb2312" %>
<%@ page contentType="text/html;charset=iso8859-1" %>

内存中(unicode):4e 2d

servlet/class(utf-8):e4 b8 ad

内存中(unicode):4e 2d

out(iso8859-1):3f

浏览器(iso8859-1):?

浏览器(gb2312):?

第四种情况

<%@ page pageEncoding="gb2312" %>
<%@ page contentType="text/html;charset=gb2312" %>

内存中(unicode):4e 2d

servlet/class(utf-8):e4 b8 ad

内存中(unicode):4e 2d

out(gb2312):d6 d0   

浏览器(iso8859-1): ⊙ ⊙

浏览器(gb2312):中

服务器端接受get请求带参数输出"中"字的情形,如

在浏览器地址栏敲入http://localhost/?name=中然后回车

tomcat默认当作iso8859-1字符集处理。这时候pageEncoding对请求过来的参数没有作用。

第一种情况

<%@ page contentType="text/html;charset=iso8859-1" %>

内存中(unicode):00 d6 00 d0

out(iso8859-1):d6 d0   

浏览器(iso8859-1): ⊙ ⊙

浏览器(gb2312):中

第二种情况

<%@ page contentType="text/html;charset=gb2312" %>

内存中(unicode):00 d6 00 d0

out(gb2312):3f 3f   

浏览器(iso8859-1):? ?

浏览器(gb2312):? ?

但是如果经过(大家经常用到)

name = new String(name.getBytes("iso8859-1", "gb2312");

结果是

第一种情况

<%@ page contentType="text/html;charset=iso8859-1" %>

内存中(unicode):00 d6 00 d0

new String(unicode):4e 2d

out(iso8859-1):3f

浏览器(iso8859-1):?

浏览器(gb2312):?

第二种情况

<%@ page contentType="text/html;charset=gb2312" %>

内存中(unicode):00 d6 00 d0

new String(unicode):4e 2d

out(gb2312):d6 d0

浏览器(iso8859-1): ⊙ ⊙

浏览器(gb2312):中

同理可以分析utf8。

像上面那样把每一次数据的编码转换都分析清楚,解决乱码问题就好办了。

上面的分析都基于一个前提:中文windows下提交数据都是以gb2312编码,但IE的”高级“中有一个“总是使用utf8提交数据”的选择,我勾上后get提交,却没有出现理解中的乱码,接着使用Proxy抓取tcp数据包分析依然看到是gb2312的d6 d0,而不是utf8的e4 b8 ad,也许说的是post提交,我再试试,下篇文章讨论这个和数据库字符集问题。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值