1.编码的基本知识
1.1.为何有编码:
一开始是为了和计算机进行沟通,出现了英文的ASCII码;后来因为各个国家语言不同,也有自己的一套编码格式,所以出现了ISO8859系列。Unicode等
1.2.编码的种类:
①ASCII:用一个字节的7位进行表示,只能表示128个字符,不支持中文
②ISO8859-1:用一个字节的8位进行表示,可以支持256个字符,不支持中文
③GBK:针对中文的编码格式,每个中文字符用两个字节表示
④Unicode:为了实现编码的统一,这是一种规范。其中包括UTF-8、UTF-16等;UTF-16用两个字节表示字符。UTF-8用边长的字节表示字符,UTF-8的编码格式如下
0xxxxxxx 110xxxxx 10xxxxxx 1110xxxx 10xxxxxx 10xxxxxx 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx |
比如,你 用Unicode的编码十六进制为 4f60
转化为二进制的话,那么为:0100 1111 0110 0000 16位,符合UTF-8 三个字节
所以用UTF-8 表示为 1110 0100 1011 1101 1010 0000 也就是 e4 bd a0、
如果用UTF-16 表示的话,因为它使用两个字节表示一个字符,所以还是 0100 1111 0110 0000 当然,有些字符使用一个字节就可以表示了
(扩展:如果打印出unicode的时候,会发现[-2, -1, 0, 97]-2,1表示这代表是unicode格式(代表ff,fe),0和97表示a (unicode统一用2个字节表示英文和和中文内容))
注意:getBytes 编码解码的解密默认为" UTF-8"(具体可看源码)
1.3.编码输出
public class TestBM { public static void main(String args[]) throws UnsupportedEncodingException{ show("你".getBytes("unicode")); show("你".getBytes("UTF-16"));
show("你".getBytes()); show("你".getBytes("UTF-8"));
show("你".getBytes("GBK")); show("你".getBytes("ISO8859-1")); } public static void show(byte[] bs){ for(int i=0;i<bs.length;i++){ System.out.println(bs[i]); } System.out.println("______"); } } 结果 -2 -1 79 96 ______ -2 -1 79 96 ______ -28 -67 -96 ______ -28 -67 -96 ______ -60 -29 ______ 63 ______ |
2.编码出错的根本原因:
编码与解码的类型对应不上。
3.编码错误类型的匹配(使用不同编码看看编码后的中文样子)
3.1.中文变为一个?号:
如果编码和解码的字符集都是一致的,那么可以确定该字符编码不支持中文,例如:ISO-8859-1
System.out.println(new String("你".getBytes("ISO8859-1"))); |
分析:你 本来对应的unicode为4f60 但是iso-8859-1为单字节编码,此时4f60已经超出它的范围,于是使用3f代替,3f在iso-8859-1中表示的时问号?
3.2.中文变为两个?号:
中文经过多次编码且其中有一次编码或者解码使用了不支持中文的字符集
new String(new String("你".getBytes("GBK"),"ISO8859-1").getBytes("GBK"),"GBK") |
过程为:gbk编码、iso解码、gbk编码、gbk解码
分析:gbk编码、iso解码 后为“Äã”这两个字符进行gbk编码解码均为?
3.3. 中文变奇怪字符,
如:ä½ å¥½ 或者 ÄãºÃ Ì Ô £ ¡Î Ò Ï²»¶ £ ¡:编码和解码的不对应,有一个ISO8859-1
(new String("你".getBytes("GBK"),"ISO8859-1") Äã (new String("你".getBytes("UTF-8"),"ISO8859-1") ä½ new String("淘".getBytes("GBK"),"ISO8859-1") ÌÔ |
3.4 出现菱形问号�:
是Unicode中的"REPLACEMENT CHARACTER",该字符的主要作用是用来表示不识别的字符,所以一般是涉及到UTF-8 以及 UTF-16
new String("你".getBytes("GBK"),"UTF-8") �� new String("你".getBytes("UTF-8"),"GBK") 浣� new String("你".getBytes("UTF-16"),"GBK") �O` new String("你".getBytes("UTF-8"),"UTF-16") � new String("你".getBytes("UTF-16"),"UTF-8") ��O` new String("你".getBytes("GBK"),"UTF-16") 쓣 |
4.编码出错常发生的地方
4.1.对应URL的传送
firefox对url中出现的中文使用了UTF-8的编码方式。之所以url中出现%,这是因为根据URL编码规范,浏览器会将非ASCII字符编成16进制后,每个字节前需要加%。
http://localhost:8080/fdyuntu-ssm/manager/codec/%E4%BD%A0%E5%A5%BD |
4.2.在HTTP中,post和get
通过request获取参数的时候(request.getParamter)的时候,默认使用的时ISO8859-1进行解码(可以查找)
处理的时候,在第一次调用request.getParamter 前设置解码的编码
如:request.setCharacterEncoding(“utf-8”)
参考链接
https://blog.csdn.net/u013905744/article/details/52456417/
https://www.cnblogs.com/yuanfy008/p/6937803.html
https://www.cnblogs.com/maohuidong/p/8044568.html
https://blog.csdn.net/u011159417/article/details/49612299
https://www.jianshu.com/p/63c7ad13907a
https://blog.csdn.net/baixiaoshi/article/details/40786503