一个关于字符编码转换特别奇怪的问题

您现在的位置:&&&&&&&&&&&&文章内容
快捷导航:
JAVA中文字符编码问题详解
来源:考试大&&&【考试大:中国教育考试第一门户】&&&日
  四、JSP读取request.getParameter里的中文参数后,在页面显示为乱码。
  在JAVA的WEB应用中,对request对象里的parameters的中文处理一直是常见也最难搞的一只大怪兽。经常是刚搞定了这边,那边又出了乱 码。而导致这种复杂性的,主要是此过程中字符编解码次数非常多,而且无论是浏览器还是WEB服务器特别是TOMCAT总是不能给我们一个比较满意的支持。
  首先我们来分析用GET方式上传参数的乱码情况。
  例如我们在浏览器地址栏输入以下URL:http://localhost:8080/test/test.jsp?param=大家好
  我们的JSP代码如此处理param这个参数:
  &% String text = request.getParameter("param");& %&
  &%=text%&
  而就这么简单的两句代码,我们很有可能在页面上看到这样的乱码:?ó????
  网上对处理request.getParamter中的乱码有很多文章和方法,也都是正确的,只是方法太多让人一直不明白到底是为什么。这里给大家分析一下到底是怎么一回事。
  首先,我们来看看与request对象有哪些相关的编码设置:
  1. JSP文件的字符编码
  2. 请求这个带参数URL的源页面的字符编码
  3. IE的高级设置中的选项“总以utf-8方式发送URL地址”
  4. TOMCAT的server.xml中配置URIEncoding
  5. 函数request.setCharacterEncoding()
  6. JS的encodeURIComponent函数与JAVA的URLDecoder类
  这么多条相关编码设置,也难怪大家被搞得头晕了。这里给大家根据各种情况给大家一一分析一下。见下表:
  以上表格里的现象,除了指名在IE7上,其他全是在IE6上测试的结果。
  由这个表我们可以看到,IE的“总以utf-8方式发送URL地址”设置并不影响对parameter的解析,而从页面请求URL和从地址栏输入URL居然也有不同的表现。
  根据这个表列出的现象,大家只要用smartSniff抓几个网络包,并稍稍调查一下TOMCAT的源代码,就可以得出以下结论:
  1. IE设置中的“总以utf-8方式发送URL地址”只对URL的PATH部分起作用,对查询字符串是不起作用的。也就是说,如果勾选了这个选项,那么类似http://localhost:8080/test/大家好.jsp?param=大家好这种URL,前一个“大家好”将被转化成utf-8形式,而后一个并没有变化。这里所说的utf-8形式,其实应该叫utf-8+escape形式,即%B4%F3%BC%D2%BA%C3这种形式。
  那么,查询字符串中的中文字符,到底是用什么编码传送到服务器的呢?答案是系统默认编码,即GBK。也就是说,在我们中文操作系统上,传送给WEB服务器的查询字符串,总是以GBK来编码的。
  2. 在页面中通过链接或location重定向或open新窗口的方式来请求一个URL,这个URL里面的中文字符是用什么编码的?答:是用该页面的编码类型。也就是说,如果我们从某个源JSP页面上的链接来访问http://localhost:8080/test/test.jsp?param=大家好这个URL,如果源JSP页面的编码是UTF-8,则大家好这几个字的编码就是UTF-8。
  而在地址栏上直接输入URL地址,或者从系统剪贴板粘贴到地址栏上,这个输入并非从页面中发起的,而是由操作系统发起的,所以这个编码只可能是系统的默认 编码,与任何页面无关。我们还发现,在不同的浏览器上,用链接方式打开的页面,如果在地址栏上再敲个回车,显示的结果也会不同。IE上敲回车后显示不变 化,而傲游上可能就会有乱码或乱码消失的变化。说明IE上敲回车,实际发送的是之前记忆下来的内存中的URL,而傲游上发送的从当前地址栏重新获取的 URL。
  3. TOMCAT的URIEncoding如果不加以设置,则默认使用ISO-8859-1来解码URL,设置后便用设置了的编码方式来解码。这个解码同时包 括PATH部分和查询字符串部分。可见,这个参数是对用GET方式传递的中文参数最关键的设置。不过,这个参数只对GET方式传递的参数有效,对POST 的无效。分析TOMCAT的源代码我们可以看到,在请求一个页面时,TOMCAT会尝试构造一个Request对象,在这个对象里,会从 Server.xml里读取URIEncoding的值,并赋值给Parameters类的queryStringEncoding变量,而这个变量将在 解析request.getParameter中的GET参数时用来指导字符解码。
  4. request.setCharacterEncoding函数只对POST的参数有效,对GET的参数无效。且这个函数必须是在第一次调用 request.getParameter之前使用。这是因为Parameters类有两个字符编码参数,一个是encoding,另一个是 queryStringEncoding,而setCharacterEncoding设置的是encoding,这个是在解析POST的参数是才用到 的。
  所以,这就导致了我们通常都要分开处理POST和GET的字符编码,用TOMCAT自带的filter只能处理POST的,另外要设置URIEncoding来设置GET的。这样很麻烦而且URIEncoding无法根据内容来动态区分编码,总还是一个问题。
  在调查TOMCAT的代码时发现了另一个在server.xml里的参数useBodyEncodingForURI,可以解决这个问题。这个参数设成 true后,TOMCAT就会用request.setCharacterEncoding所设置的字符编码来同样解析GET参数了。这样,那个 SetCharacterEncodingFilter就可以同时处理GET和POST参数了。
  知道了以上知识后,我们再来分析一下前面表格中列出的几个典型现象。
  第一条,请求源页面的编码为UTF-8,而TOMCAT的URIEncoding未指定,则TOMCAT用ISO8859-1方式来解码参数,所以从request中读出来后,内存中存储的为错误的UNICODE数据,导致之后到屏幕显示的所有转换全部出错。
  第九条,请求源页面编码为GBK,而TOMCAT的URIEncoding也为GBK,TOMCAT用GBK方式去解码原本用GBK编码的字符,解码正确,内存中的UNICODE值正确,最终显示正确的中文。
  第十三条,请求源页面编码为UTF-8,TOMCAT的URIEncoding也为UTF-8,而在IE6中最终显示的中文字符,如果是奇数个数,则最后一个会显示为乱码。这是为什么呢?
  我的猜测是,这是因为IE6将URL地址发送时,对查询字符串是直接对UTF-8格式的字符使用GBK来编码,而不是对UNICODE的字符来用GBK编 码,所以UTF-8的数据没有经过UNICODE而直接编码成了GBK。而到了TOMCAT这边,GBK的编码又被当成UTF-8做了解码。所以这个过程 中经过了UTF-8转换成GBK,然后又从GBK转换成UTF-8的过程,而这种转换,恰好就会出现奇数个中文字符串的最后一位为乱码的现象。而在IE7 中,估计把这种现象当做BUG已经被解决了,即在发送地址时会先转成UNICODE再编码成GBK。那么估计在IE7的浏览器+中文操作系统环境下,如果 我们把TOMCAT的URIEncoding设置成GBK,无论JSP编码成什么格式,都不会出现乱码。这个没测试,请大家自己验证。
  其他几条就不再做分析了,有兴趣的大家自己分析。
  五、对URL做Encode和Decode
  对于request参数的中文乱码问题,个人觉得最好的还是用URLEncode/URLDecode,因为如果你的WEB站点要支持国际化,最好就是保证从IE递送过来的参数永远是正确的UTF-8编码。
  在IE端,我们可以用JS脚本来对参数编码:encodeURIComponent(),编码后中文字符便变成了%B4%F3%BC%D2%BA%C3这 种形式。在JAVA端,可以用java.net.URLDecoder.decode来解码。不过这里要注意一个问题,就是TOMCAT会自动先对URL 做一次decode,我们可以在TOMCAT的UDecoder类中看到这一点。不过TOMCAT并非使用了URLDecoder.decode,而是自 己编写了一个decode函数。网上有些文章上介绍过一种处理乱码的方法便是在JS中对参数做两次encodeURIComponent,在JAVA中做 一次decode,可以解决一些没有设置URIEncoding时发生的乱码问题。不过个人觉得如果弄懂了整个字符编码转换的过程,基本上是用不到这种方 法的。
  六、从数据库中读取中文字符数据,在页面上显示为乱码。
  对于数据库中读取中文字符出现乱码的问题,本人遇到的还比较少,所以暂时没有总结。如果大家有类似的经验,欢迎补充说明,我一定注明作者身份。
  好了,对各种字符乱码问题的分析就总结到这里,相信只要把握“以指定编码读取--转换为UNICODE--以指定编码输入”这基本步骤,初学者也可以很快 分析出字符乱码的根源所在。另外我建议不要随便使用new String(str.getBytes(enc1),enc2)这种方式来强行转码,也不要随便使用网上的字符转码函数,我觉得只会把问题隐藏更深更复 杂化。我们应该清晰地分析整个字符流的编解码过程,自然可以找出乱码的根源所在,从而保证整个字符流动中,在内存中的UNICODE始终是正确的。
来源:考试大-
责编:xxm&&&
模板不存在,请添加模板后再生成!E:\wwwroot\www_233_com\Templets\three\Templets\soft\small\cont_b_st.htm
暂无跟贴,欢迎您发表意见
考试大Java认证评论排行
1.&&评论4条
2.&&评论2条
3.&&评论2条
4.&&评论2条
5.&&评论1条
6.&&评论1条
12345678910
12345678910
123456SCJP考试题310-025(第二套)19-50/1477SCJP考试题310-025(第二套)51-91/147
12345678910关于记事本的一个很有意思的现象_百度知道
关于记事本的一个很有意思的现象
亲爱的朋友们,请你们按照下边的步骤操作一下,然后告诉我结果:右键新建一个TXT文本文档打开这个新建的TXT文件,写下“联通通联”4个字(不包括引号)保存文件,然后再重新打开请问你的记事本里写着什么?(将采纳最先答对的)不要告诉我是原来那4个字,本人亲自验证的,绝非原来的4个字
本来呢昨天晚上心情不错,提问了个有趣的问题,结果出了一件事让我很不高兴!昨天我收到了一条欺诈信息,说是【您好!感谢您使用百度服务。 您的回答可能违反了知道内容规范。 系统监测已进行封禁处理。 为了保障您的帐号能正常使用。 请点击 (为了防止你们不小心点击到,我就不写了) 解除封禁,为了保障您帐号的安全性。 请在24小时内完成验证】我查看了其源代码,是盗号网页:其源代码中含有【&li&&a href=&#&&/a&&/li&】语句,这是指向本页面的意思,而不是打开新链接!最可怕的是,该网址除了少数杀软之外,大部分杀软都把它评定为安全网址了!鉴别方法:1.该盗号网址中不含有“baidu”字样,不是百度官网!2.点击该该盗号网址中的“忘记密码”,没有出现修改密码的功能,更别提密保手机和服务电话了!3.当你填写的用户名和密码为空时,显示“%1 不是有效的win32位程序”,说明这个页面是带木马的。所以我连夜通知了那些无知的杀软,以及很多团队,就没来得及采纳你的答案。这样吧,给你再加50分。希望朋友能通知更多的团队,以防上当受骗!
提问者采纳
简单的说是微软的编码bug记事本都会用自动用UTF-8编码保存(而非ANSI)。“联”的UTF-8编码是54 80。记事本在保存文件时虽然添加了FF FE的文件头,但是没有把“联”保存为54 80而是用了6A 00。专业的讲法,这是一个字符编码应用的奇怪现象,讲的明白点,可以说是记事本开小差了!记事本为什么会犯错误?记事本犯了怎样的错误呢?也许你会迫不及待的想知道这些问题,如果是这样,我不会让你空腹而归的。 在简体中文操作系统中默认的本地字符集编码是GBK编码,除非你在保存记事本文本文件时候选择了其他编码方式,否则用记事本录入的字符信息将使用GBK编码进行储存。巧合的是,“联通”这两个字符的GBK编码具有UTF-8编码的特征,记事本犯下的错误正是将GBK编码存放的记录有“联通”两个字符的文件误认为UTF-8编码的文件。或许你会问,UTF-8编码的文件不是以“EF BB BF”三个特殊字节开头吗?既然这样,记事本怎么会犯这么低级的错误呢?没错,UTF-8编码规定使用UTF-8编码的文件以“EF BB BF”三个特殊字节开头,但并不是强制性要求,早期的UTF-8编码文件就不遵循这个规定。因此记事本不能依靠文件的开头字节判断一个文件是否是UTF-8编码,而只能对文件中的数据进行简单的编码分析来确定。正是这个原因,才有了字符编码应用中的这个奇怪又无法避免的现象。 [细节] 如果上面的解释对于你来说只是杯开胃红酒,那我还是块点把主食呈上吧,一份大峡谷香烤猪肋排。UTF-8编码采用1-3个字节对字符进行编码,编码字节数与字符的Unicode编码值有严格的对应关系,让我们回忆下UTF-8编码和Unicode的对应关系吧。 Unicode编码值 UTF-8编码结构 \u0001 - \u007E 0XXXXXXX \u0080 - \u07FF 和 \uXXXXX 10XXXXXX \u0800 - \uFFFF 1110XXXX 10XXXXXX 10XXXXXX “联通”这两个字符的GBK编码值是“C1 AA CD A8&,GBK编码方式使用两个字节对一个字符进行编码,因此以GBK编码方式存放的录有“联通”两个字符的文件的大小为四个字节。接下来分别观察“联通”这两个字符GBK编码值的二进制形式,你有发现有趣的事。 联 GBK 十六进制:C1 AA 二进制:10 1010 通 GBK 十六进制:C1 AA 二进制:10 1000 请注意上面二进制数据的着色部分,你想到了什么?对,它们和UTF-8编码结构中的补充位完全一致,UTF-8编码的补充位使得编码值更有规律,而记事本刚好凭借这个特征区分UTF-8编码的文件。存有“联通”两个字符的文件的所有数据都符合这个特征,就是这样,记事本彻底的将文件误认为UTF-8编码的文件。 将错就错,让我们来看看这个错误是怎样收场的。如果把“联通”的GBK编码值当作UTF-8编码值,那文件就成为一个写有数据“C1 AA CD A8”并以UTF-8编码的文件,当使用记事本再次打开的时候会看到什么呢?只要将UTF-8编码转换成Unicode编码就知道了。UTF-8编码“C1 AA CD A8”转换成Unicode编码后,编码值为“6A 00 68 03”(转换方法请参考本Blog中的《字符编码》一文)。0x006A这个Unicode编码值位于\u0001 - \u007E之间,若要转换为UTF-8编码,显然只能用一个字节进行编码,因此“联”的GBK编码“C1 AA”虽然特征上貌似UTF-8编码,但它却不对应任何一个UTF-8编码。接着看0x0368这个Unicode编码值,这个值对应了字符“ͨ”,这也正是我们将在记事本中看到的内容。或许你会说我看到的是一个黑色矩形啊,这只是字体的原因,你将字体改为宋体或者其他字体,看到的就是字符“ͨ”。 对于中文字符,UTF-8编码要用三个字节进行编码,因此,如果你使用记事本录入“联通”,然后选择以UTF-8编码方式保存的话,文件大小应为9个字节(包含三个字节的开头数据),而同样的文件GBK编码却是4个字节。最后附上“联通”的GBK、UTF-8、Unicode编码值,以及记事本的错误思维。 联通 GBK C1 AA CD A8 UTF-8 E8 81 94 E9 80 9A Unicode 54 80 1A 90 联通 GBK C1 AA CD A8 UTF-8 C1 AA CD A8 Unicode 6A 00 68 03 (将GBK值误认为UTF-8值的结果) 希望能帮到你,不知道你满意吗?
本来呢昨天晚上心情不错,提问了个有趣的问题,结果出了一件事让我很不高兴!追问写不开,写题目补充了。我给再加50分。希望朋友能通知更多的团队,以防上当受骗!
提问者评价
其他类似问题
为您推荐:
等待您来回答
下载知道APP
随时随地咨询
出门在外也不愁后使用快捷导航没有帐号?
只需一步,快速开始
查看: 2198|回复: 7
DW CS5出了超级奇怪问题,关于文件编码的,求教
UID534759在线时间 小时积分523帖子离线16676 天注册时间
高级会员, 积分 523, 距离下一级还需 477 积分
我用DW5打开CSS文件,用的GB2312编码(因为网站程序就是这个编码,没办法),可我把原来的代码删除,写几行代码,保存再重新打开,就发现编码变成UTF-8了,这不莫名其妙吗?我用记事本打开,改写代码,然后不保存成UTF-8的,再用DW打开,又变了……我直接从网站程序目录里下了一个GB2312编码的CSS,打开,没问题。在里面改两句代码,没问题,全选,替换成我之前写的代码,又变成UTF8,这是哪根筋搭错了?
我用CTRL+J改编码,提示说这里面有一些字符不支持,可能会变成问号,我确定,没有任何字符变成问号,看看代码:
#hot {
& & & & background: #FC6;
& & & & height: 150
& & & & margin: 0
& & & & width: 960
}复制代码
这代码有鸟毛病?
UID381636在线时间 小时积分16845帖子离线16676 天注册时间
可能有看不见的如全角空格的字符。
以前都先copy下,再转码,以确保安全。
UID534759在线时间 小时积分523帖子离线16676 天注册时间
高级会员, 积分 523, 距离下一级还需 477 积分
原帖由 [i]yoom 于
11:33 发表
可能有看不见的如全角空格的字符。
以前都先copy下,再转码,以确保安全。
下面这句什么意思?没看懂。
我各种方法都试过了,包括用记事本打开CSS,再在记事本里复制那个代码,粘贴到DW里,依然会变成UTF8
UID381636在线时间 小时积分16845帖子离线16676 天注册时间
有时候,DW提示转码可能会有问题是有道理的,因此稳妥的办法是先复制一份,转码后再粘贴保存。
防止乱码后,不可恢复的问题。
我咋没有遇到这个问题呢。也有最后的办法,找到一个gbk编码的文件,复制一个,然后DW打开,再粘贴你的内容,应该就没有问题了吧。
UID3771在线时间 小时积分12744帖子离线16676 天注册时间
Ctrl+U,新建文档——默认编码里设置成GB2312后,再试试。
UID534759在线时间 小时积分523帖子离线16676 天注册时间
高级会员, 积分 523, 距离下一级还需 477 积分
原帖由 [i]yoom 于
13:34 发表
有时候,DW提示转码可能会有问题是有道理的,因此稳妥的办法是先复制一份,转码后再粘贴保存。
防止乱码后,不可恢复的问题。
我咋没有遇到这个问题呢。也有最后的办法,找到一个gbk编码的文件,复制一个,然后 ...
我就是先弄一个GBK编码的CSS,然后我把里面的内容换成我的,然后就自动变成UTF8了。要不然我早解决这问题了……
UID534759在线时间 小时积分523帖子离线16676 天注册时间
高级会员, 积分 523, 距离下一级还需 477 积分
又沉了,拜托大家帮帮忙,很着急
UID400972在线时间 小时积分92帖子离线16676 天注册时间
初级会员, 积分 92, 距离下一级还需 108 积分
初步分析我认为可能是编码的问题,你手输入你的编码试一试看是否会被更改成utf-8,如果还是出现 看看其编码设置上更改为默认的编码为gb2312试一试 看是否会被改变(如果是在网上copy的注意其可能被转换的字体,试用记事本另存为ANSI编码)
Powered by

我要回帖

更多关于 tomcat字符编码设置 的文章

 

随机推荐