字符编码

来源:互联网 发布:node2vec 知乎 编辑:程序博客网 时间:2024/06/06 07:04

乱码问题

乱码问题是开发中经常碰到的问题,每次遇到这种问题都是从网上搜解决方案,然后拷贝代码去试,不行再去找,成功解决就放一边了,开发完成后也不去追究究竟是什么原因造成的乱码问题,只知道是编码问题,但如果进一步问,是什么样的编码问题导致的就不得而知了。
其实编码没有那么深奥,可以这样理解:计算机在存储字符时,使用的是二进制的数字,为了存储字符,就需要制定一套规则用于将二进制的数字与字符一一对应起来,这样形成的一套规则就叫编码规则,而这套规则包含的所有字符组成一个字符集。那么,在使用该编码规则对将字符转换成二进制存储起来,那么当需要取字符时,很显然也只能使用这套规则就二进制数字进行解码。那么乱码的原因就是因为编码和解码使用了不同的编码规则,并且解码使用的编码规则不兼容编码时编码规则,导致二进制数字不能被正常解析,出现乱码。
有了这样的理解后,接下来就需要了解下常用的编码规则都有哪些,这些规则之间的不同之处是什么。

编码及字符集

  • ASCII及ISO8859-1

    ASCII是美国信息交换标准代码的英文(American Standard Code for Information Interchange)首字母缩写,使用单字节表示一个字符,总共有7位,表示的字符集有128个字符。ISO8859-1是ASCII的扩展字符集,也是单字节编码,但是使用了8位来表示,字符集中有256个字符。按照字符的二进制数字大小排列,前128个字符完全相同,因此使用ASCII编码的字符可以使用ISO8859-1进行解码。

  • GB及GBK

    GB及GBK是适用于汉字的编码方式,按照时间先后主要有以下几种:
    • GB2312 中国国家标准简体中文字符集,收录了6763个汉字。采用2个字节来表示,规定:一个小于127的字符的意义与原来相同,但两个大于127的字符连在一起时,就表示一个汉字,前面的一个字节。
    • GBK 汉字内码扩展规范,K为汉字“扩展”的拼音首字母大写。是GB2312的扩展,汉字和字符更多,向下完全兼容GB2312,因此使用GB2312编码的汉字,可以使用GBK进行解码。
    • GB18030 国家标准 GB-18030-2005《信息技术中文编码字符集》是最新的内码集,有70244个汉字,向下完全兼容GB2312和GBK。多字节编码,单字节双字节和四字节。

    以上三种的0-128与ASCII完全一致,即兼容ASCII编码

  • UTF-8/UTF-16
    • UTF-8 8-bit Unicode Transformation Format ,可变长度字符编码,与ASCII兼容。

Java Web中的编解码

Java的网络通信采用ISO8859-1编码方式,因此HTTP请求在传递之前都要经过ISO8859-1编码后进行传输,而后在接收端再使用ISO8859-1进行解码。比如传递一个参数是中文,中文是GBK编码的,将参数使用GBK编码后,再使用ISO8859-1解码。解码后进行传输,浏览器接收后使用GBK进行编码,再使用ISO8859-1进行解码,得到正确的字符。整个过程如下面的代码所示:

    public static void main(String[] args) throws UnsupportedEncodingException {        String s = "你好";                   //服务器端,对汉字字符串进行GBK编码,再使用ISO8859-1进行解码,传输解码后的字符串        // 编码          byte[] gbk = s.getBytes("gbk");          // 解码         String s3 = new String(gbk, "iso8859-1");                   //客户端接收到上s3后,先使用iso8859-1进行编码,再使用gbk进行解码,得到原始字符        s3 = new String(s3.getBytes("iso8859-1"), "gbk");                    System.out.println(s3);                  }

如果不进行上述操作时,直接传递字符串s,相当于直接传递的是s的ISO8859-1的编码,那么浏览器在接收到s的ISO8859-1的编码后,无论使用任何解码方式都没办法正常解码,出现乱码:

    public static void main(String[] args) throws UnsupportedEncodingException {                //服务器端对s不做任何处理,网络传输时s会被按照iso8859-1进行编码        String s = "你好";                  //客户端接收到上s的编码二进制后,无论使用GBK还是UTF-8或者其他任一一种编码方式都无法解析出正确的s        String s3 = new String(s.getBytes("iso8859-1"), "iso8859-1");        String s4 = new String(s.getBytes("iso8859-1"), "GBK");        String s5 = new String(s.getBytes("iso8859-1"), "UTF-8");                  System.out.println(s3);        System.out.println(s4);        System.out.println(s5);                }

所以,在服务器端在发送汉字时,最稳妥的办法时,对汉字使用GBK或者UTF-8(UTF-8字符集也包含汉字)进行编码,最好是使用UTF-8进行编码因为有些浏览器比如Safari不支持GBK而UTF-8大多都支持,再使用ISO8859-1进行解码。这样汉字乱码问题就解决了。

原创粉丝点击