Open alwaystest opened 8 years ago
标签(空格分隔): JSP
不是第一次遇到这个问题。当时使用了重组String的方法来解决,也知道产生乱码的原因是编码和解码的时候使用的字符集不一致,但是时间久了,难免忘记当时的心得,而且限于眼界,当时对这个问题也没有进行深究,今天又折腾了半天,记录一下,如果将来有更深入的研究,再来完善。
首先,Java的Class文件内部编码采用UTF-16,特殊情况下编译时才会需要手动指定源文件编码格式,所以源文件的编码方式不会导致中文乱码出现,比如
//fileEncoding = GBK String data = "你好"; printWriter.write(data);
服务器端接收到的并不是GBK编码的字节流。
使用Post方式访问Tomcat服务器时,服务器默认使用ISO-8859-1来解析收到的数据。设置request.setCharacterEncoding("UTF-8")可以使服务器强制使用"UTF-8"编码集对收到的数据进行解码。而正常情况下应该在发送Post请求的时候在HTTP头中通过Content-Type指定字符串的编码方式。这样Tomcat就可以根据HTTP头中的信息指定编码集进行解码,此时中文解析正常。
request.setCharacterEncoding("UTF-8")
Content-Type
使用Get方式访问Tomcat服务器时,默认采用ISO-8859-1来解析收到的数据,即使设定了request.setCharacterEncoding("UTF-8"),也不会生效,是因为Tomcat服务器的conf/service.xml 中设定<Connector>中的useBodyEncodingForURI=false(默认)。设定为useBodyEncodingForURI=true就可以使request.setCharacterEncoding("UTF-8")生效。或者在<Connector>中通过设定URIEncoding="UTF-8"指定Get方式默认使用UTF-8来解码。
ISO-8859-1
conf/service.xml
<Connector>
useBodyEncodingForURI=false(默认)
useBodyEncodingForURI=true
URIEncoding="UTF-8"
UTF-8
经过这样的设定之后,就不用使用new String(bytes, encoding)的方式来解析中文了。我不喜欢用重建String的方式,要打的代码太多了。
new String(bytes, encoding)
IE对URL中的中文默认好像不是使用UTF-8来编码的,所以这个时候IE访问带中文的URL还是乱码。嗯,我不打算兼容IE。
参考:
从Tomcat的中文乱码问题谈Java编码机制
Tomcat关于encoding编码的默认设置以及乱码产生的原因
又进行了测试:
String data = "username=你&password=1"; LogUtil.d("Bytes", Arrays.toString(data.getBytes("iso-8859-1"))); LogUtil.d("Bytes", Arrays.toString(data.getBytes("utf-8"))); LogUtil.d("Bytes", Arrays.toString(data.getBytes("GBK"))); /* [117, 115, 101, 114, 110, 97, 109, 101, 61, 63, 38, 112, 97, 115, 115, 119, 111, 114, 100, 61, 49] [117, 115, 101, 114, 110, 97, 109, 101, 61, -28, -67, -96, 38, 112, 97, 115, 115, 119, 111, 114, 100, 61, 49] [117, 115, 101, 114, 110, 97, 109, 101, 61, -60, -29, 38, 112, 97, 115, 115, 119, 111, 114, 100, 61, 49] */ System.out.println(Arrays.toString("你".getBytes("iso-8859-1"))); System.out.println(Arrays.toString("你".getBytes("utf-8"))); System.out.println(Arrays.toString("你".getBytes("GBK"))); System.out.println(Arrays.toString(request.getParameter("username").getBytes())); System.out.println(Arrays.toString(request.getParameter("username").getBytes("ISO-8859-1"))); System.out.println(Arrays.toString(request.getParameter("username").getBytes("UTF-8"))); System.out.println(Arrays.toString(request.getParameter("username").getBytes("GBK"))); /* [63] //你 iso-8859-1 [-28, -67, -96] //你 utf-8 [-60, -29] //你 gbk [63, 63, 63] //无参 [-28, -67, -96] //iso-8859-1 [-61, -92, -62, -67, -62, -96] //utf-8 [63, 63, 63] //gbk */
方便对比,只把"你"的Bytes输出来。
//Android [63] //iso-8859-1 [-28, -67, -96] //utf-8 [-60, -29] //gbk //server [63] //你 iso-8859-1 [-28, -67, -96] //你 utf-8 [-60, -29] //你 gbk //服务器接收到的 [63, 63, 63] //无参 [-28, -67, -96] //iso-8859-1 [-61, -92, -62, -67, -62, -96] //utf-8 [63, 63, 63] //gbk
发现我的服务器getBytes()是用的GBK。(数据使用post发送)。
getBytes()
使用iso-8859-1解码收到的数据,正是"你"的utf-8编码格式。
iso-8859-1
utf-8
所以使用new String(data.getBytes("iso-8859-1"),"utf-8");可以正确的解析出原来的汉字。
new String(data.getBytes("iso-8859-1"),"utf-8");
使用Chrome的开发者工具查看发送的Get请求。发现"你"的编码是%E4%BD%A0,转换为Byte数据,刚好是[-28,-67,-96]。
%E4%BD%A0
[-28,-67,-96]
所以使用Android的HttpURLConnection的Post方法,发送的数据默认就是UTF-8编码的。
Tomcat解析URL中文乱码问题
标签(空格分隔): JSP
不是第一次遇到这个问题。当时使用了重组String的方法来解决,也知道产生乱码的原因是编码和解码的时候使用的字符集不一致,但是时间久了,难免忘记当时的心得,而且限于眼界,当时对这个问题也没有进行深究,今天又折腾了半天,记录一下,如果将来有更深入的研究,再来完善。
首先,Java的Class文件内部编码采用UTF-16,特殊情况下编译时才会需要手动指定源文件编码格式,所以源文件的编码方式不会导致中文乱码出现,比如
服务器端接收到的并不是GBK编码的字节流。
使用Post方式访问Tomcat服务器时,服务器默认使用ISO-8859-1来解析收到的数据。设置
request.setCharacterEncoding("UTF-8")
可以使服务器强制使用"UTF-8"编码集对收到的数据进行解码。而正常情况下应该在发送Post请求的时候在HTTP头中通过Content-Type
指定字符串的编码方式。这样Tomcat就可以根据HTTP头中的信息指定编码集进行解码,此时中文解析正常。使用Get方式访问Tomcat服务器时,默认采用
ISO-8859-1
来解析收到的数据,即使设定了request.setCharacterEncoding("UTF-8")
,也不会生效,是因为Tomcat服务器的conf/service.xml
中设定<Connector>
中的useBodyEncodingForURI=false(默认)
。设定为useBodyEncodingForURI=true
就可以使request.setCharacterEncoding("UTF-8")
生效。或者在<Connector>
中通过设定URIEncoding="UTF-8"
指定Get方式默认使用UTF-8
来解码。经过这样的设定之后,就不用使用
new String(bytes, encoding)
的方式来解析中文了。我不喜欢用重建String的方式,要打的代码太多了。IE对URL中的中文默认好像不是使用
UTF-8
来编码的,所以这个时候IE访问带中文的URL还是乱码。嗯,我不打算兼容IE。参考:
从Tomcat的中文乱码问题谈Java编码机制
Tomcat关于encoding编码的默认设置以及乱码产生的原因
又进行了测试:
方便对比,只把"你"的Bytes输出来。
发现我的服务器
getBytes()
是用的GBK。(数据使用post发送)。使用
iso-8859-1
解码收到的数据,正是"你"的utf-8
编码格式。所以使用
new String(data.getBytes("iso-8859-1"),"utf-8");
可以正确的解析出原来的汉字。使用Chrome的开发者工具查看发送的Get请求。发现"你"的编码是
%E4%BD%A0
,转换为Byte数据,刚好是[-28,-67,-96]
。所以使用Android的HttpURLConnection的Post方法,发送的数据默认就是UTF-8编码的。