解析Java WEB中文乱码问题根源
4.1. 错误做法的信心从何而来
早在几年前的tomcat3年代,网上流传的种种解决方法中,就有一种声称不能给JSP指定字符集,否则会造成乱码。这是一个很奇怪的说法,似乎SUN设计的机制完全错误一样,但是何以有不少人相信并且深受其害呢?
因为中文编码本身的特性,有时候几个错误的操作,反而会得到似乎正确的结果。
比如,“中”的GB2312编码有两个字节D6 D0
1. 如果要把它作为ISO8859-1来处理,实际上是对应两个字符的,即Ö 和Ð。
2. 如果不指定用户提交数据的字符集,tomcat会以为提交的是这两个字符。
3. 经过tomcat处理之后,再次输出到相应页面,tomcat当然仍然以ISO8859-1的方式输出两个字符Ö 和Ð
4. 这样,客户端得到了ISO8859-1的ÖÐ,也就是和GB2312的“中”一样的两个字节。因此他会觉得,自己提交的数据被正确的处理了。
实际上这样的做法是非常危险的
首先,这个时候在tomcat的内部,代表这个数据的String的值不是Unicode的“中”,而是Unicode的Ö和Ð也就是4个字节(不要忘记,java的字符串既不是ISO8859-1,也不是GB2312),尽管把这两个错误的字符转为ISO8859-1的字节输出后得到了似乎正确的结果,但是如果系统中还有其他不是来自于用户输入的字符串呢?比如说来自于数据库?tomcat如果把正确的字符串按照同样的方法处理,自然就会造成乱码。
其次,因为String的内容并不是应用程序要处理的内容本身,甚至连长度都变了,所以很多字符串操作都会出现莫名其妙的错误。
最简单的例子:
下载最新的tomcat,运行
1. 访问 http://localhost/servlets-examples/servlet/RequestParamExample
2. 点击右键把字符集改成GB2312
3. 分别在两个框输入中 文
4. 提交
5. 得到一个显示乱码的页面(左)
6. 再点击右键把字符集改成GB2312
7. “中文”两个字出现了(右)
结果似乎正确,除了要手工改浏览器字符集以外(某些版本的浏览器并不需要)。但是只要使用调试器,或者直接在代码中打印用户输入的字符,就可以看到,得到的用户输入不是“中文”,而是ÖÐ ÎÄ。
这就是为什么有些应用程序“界面显示正确,但是控制台打印的都是乱码”的原因。当你知道自己看起来正确的系统中正在运行着这些奇怪的字符的时候,该考虑放弃这些错误的“捷径”了
