在了解了Java Web中可能需要编码的地方后,下面看一下,当我们碰到一些乱码时,应该怎么处理这些问题?出现乱码问题唯一的原因都是在char到byte或byte到char转换中编码和解码的字符集不一致导致的,由于往往一次操作涉及到多次编解码,所以出现乱码时很难查找到底是哪个环节出现了问题,下面就几种常见的现象进行分析。
3.6.1 中文变成了看不懂的字符
例如,字符串“淘!我喜欢!”变成了“ÌÔ£¡ÎÒϲ»¶£¡”编码过程如图3-19所示
字符串在解码时所用的字符集与编码字符集不一致导致汉字变成了看不懂的乱码,而且是一个汉字字符变成两个乱码字符。
3.6.2 一个汉字变成一个问号
例如,字符串“淘!我喜欢!”变成了“??????”编码过程如图3-20所示
将中文和中文符号经过不支持中文的ISO-8859-1编码后,所有字符变成了“?”,这是因为用ISO-8859-1进行编解码时遇到不在码值范围内的字符时统一用3f表示,这也就是通常所说的“黑洞”,所有ISO-8859-1不认识的字符都变成了“?”。
3.6.3 一个汉字变成两个问号
例如,字符串“淘!我喜欢!”变成了“????????????”编码过程如图3-21所示
这种情况比较复杂,中文经过多次编码,但是其中有一次编码或者解码不对仍然会出现中文字符变成“?”现象,出现这种情况要仔细查看中间的编码环节,找出出现编码错误的地方。
3.6.4 一种不正常的正确编码
还有一种情况是在我们通过request.getParameter获取参数值时,当我们直接调用
String value = request.getParameter(name);
会出现乱码,但是如果用下面的方式
String value = String(request.getParameter(name).getBytes("ISO-8859-1"), "GBK");
解析时取得的value会是正确的汉字字符,这种情况是怎么造成的呢? 看下如图3-22所示:
这种情况是这样的,ISO-8859-1字符集的编码范围是0000-00FF,正好和一个字节的编码范围相对应。这种特性保证了使用ISO-8859-1进行编码和解码可以保持编码数值“不变”。虽然中文字符在经过网络传输时,被错误地“拆”成了两个欧洲字符,但由于输出时也是用ISO-8859-1,结果被“拆”开的中文字的两半又被合并在一起,从而又刚好组成了一个正确的汉字。虽然最终能取得正确的汉字,但是还是不建议用这种不正常的方式取得参数值,因为这中间增加了一次额外的编码与解码,这种情况出现乱码时因为Tomcat的配置文件中useBodyEncodingForURI配置项没有设置为”true”,从而造成第一次解析式用ISO-8859-1来解析才造成乱码的。