这篇文章的主题,是谈谈我对字符集与字符编码的理解,以及在开发时我遇到过的一些问题。仅仅是浅谈。如果读者有自己的观点,也欢迎一起交流。
先声明一些基本的名词。
1.字符(char)。字符就是我们肉眼能看到的这些符号,比如“中”、“A”、“a”、“β”、“。”、“100”这些符号,这些符号来自不同语言,上述例子就有中文、英语、希腊语、标点符号、阿拉伯数字等等,这些符号我们统称为字符。
2.字符集(Charset)。字符集就是字符的集合。例如,所有中文的集合、所有英文的集合,全世界所有文字的集合(万国码Unicode)。一般常用到的字符集有GBK(包括2万多汉字)、Unicode、ASCII码、GB2312(包括几千汉字)。
3.字符编码(Encoding)。字符编码就是按照一定的规则,将字符集里的字符,以0、1的形式存储。因为在计算机底层里,只能通过0、1来记录数据,为了区分这些字符,只好以不同的0、1序列来代表这些字符。所以不同的字符集,有不同的编码方式。甚至同一个字符集有多个编码方式。
在平时,我们往往将字符集与字符编码混为一谈,例如GBK字符集的编码方式就是GBK,GB2312字符集的编码方式就是GB2312。因为这些字符集对应的编码方式只有一个,所以容易混淆。Unicode字符集就有多种编码方式,例如UTF-8、UTF-16等等。
概念的东西说完,聊聊最常见的乱码问题。
在我短短的一年工作时间里,我常遇到的一类问题是前端通过get方式请求后端,同时携带中文参数。前端编码方式和后端代码里的解码方式都是UTF-8,但是后端取出的参数值是乱码。原因就在于Tomcat服务器在接收前端的请求时,URL、请求参数是UTF-8编码没错,但是Tomcat默认的处理请求的编码方式是ISO-8859-1(7.0以及以下的Tomcat),换句话说,Tomcat已经在最外层以ISO-8859-1编码方式,对UTF-8格式的请求进行解码了,那么这一步就已经出错了,哪怕服务端是UTF-8,对这一步的乱码也无能为力。
解决方案比较简单,在后端将字符串先按照ISO-8859-1编码方式转化为byte数组,再将byte数组以UTF-8编码方式编码,即可获取真正的字符串。
String destStr = new String(srcStr.getBytes("ISO-8859-1"), "utf-8");
第二种解决方法,对请求的URL字符串进行两次EncodeURI方法,后端用URLDecoder.decode(srcStr, charset)进行解码即可。
第二种方式比较好,第一种有时不行。Post请求一般不会乱码,因为Spring项目里往往有字符编码过滤器,这过滤器仅对Post请求里的参数起作用。也可以自己写过滤器,对Get请求特殊处理。PS:Tomcat 8.0及以上的版本里,默认的处理请求方式是UTF-8,7.0及以下的是ISO-8859-1。
网友评论