tomcat乱码迷思

- 对于tomcat7,中文get请求会有乱码,因为tomcat将浏览器发过来的参数封装到request里面时,字节转字符串的时候,默认用的是iso-8859-1编码。
- 对于tomcat8,get请求里面,参数解析的时候,用的是utf-8编码,中文不会有乱码问题。
- 对于post请求来说,因为参数不是url地址里面解析出来的,而是从请求体里面解析的,因此处理情况不一样。不管是tomcat7还是8,解析时都是用iso-8859-1,因此会有乱码。需要调用request.setCharacterEncoding("utf-8")来改变默认编码。
- 对于post请求来说,除了调用request.setCharacterEncoding("utf-8")外,还有一种麻烦的处理方式:大概是这样一种写法:
String bad = request.getParameter("name");
String good = new String(bad.getBytes("iso-8859-1"), "utf-8");
这个写法很绕又麻烦,不过如何去理解它,是一件很有意思的事情。(这里写不下了。)
- 对于响应来说,我们通常会调用response.setContentType("text/html; charset=utf-8"); 来处理中文乱码。有同学说,我们能不能用iso-8859-1编码响应内容,然后浏览器那一边用iso-8859-1来解析呢。貌似只要两边对应上了就好了,或者跟post请求的处理方式类似,我用iso-8859-1和utf-8编码来回倒一下,是不是也可以呢?
不行,一个中文字符串,你用iso-8859-1去转成字节,里面的信息会丢失。
可以试一下:
System.out.println(Arrays.toString("中".getBytes("iso-8859-1")));
System.out.println(Arrays.toString("国".getBytes("iso-8859-1")));
可以发现,不同的中文,转成字节后,结果竟然是一样的。
这里关键点在于字节转字符串。以及反过来,字符串转字节。
【情况一:字节转字符串,再转字节】
假设你收到了三个字节的数据,这三个字节是一个字符,还是两个或者三个字符呢?都有可能,看你用什么样的编码去转【字节 》》字符串】。如果用utf-8,通常是一个中文字符,如果是gbk,那么就是一个半,如果是iso-8859-1,那么是三个字符。不管用哪一种,变成字符串之后,你都可以用string.getBytes("charset")把字符串还原成原来的字节。只要你前后编码一致,字节数据就不会丢失。
【情况二:字符串转字节,再转字符串】
【tomcat乱码迷思】假设你有一个中文字符,它转成字节后是几个呢?如果用utf-8,是三个;gbk是两个;iso-8859-1,是一个。一个字节最多表示511个字符,而中文字符有几万个。因此一个字节是无法表示中文的。那么在【字符串》》字节】这个环节,如果你用错了编码,信息就丢失了。你无法将字节还原成原来的字符串。("中".getBytes("iso-8859-1")和"国".getBytes("iso-8859-1"),得到的都是[63],那么63这个字节数据到底是“中”还是“国”呢?)

    推荐阅读