字符串编码

  1. utf-8中,一个字母用一个字节表示,一个汉字用三个字节表示,特殊的汉字用四个字节表示
  2. gbk中,一个字母用一个字节表示,一个汉字用两个字节表示。
  3. ISO-8859-1
    1. 单字节编码,向下兼容ASCII,其编码范围是0x00-0xFF,0x00-0x7F之间完全和ASCII一致,0x80-0x9F之间是控制字符,0xA0-0xFF之间是文字符号。
  4. GBK
    1. 采用单双字节变长编码,英文使用单字节编码,完全兼容ASCII字符编码,中文部分采用双字节编码。双字节其编码范围从8140至FEFE(剔除xx7F)。

      单字节:00000000 - 01111111

      双字节:10000001 01000000 - 11111110 11111110 (剔除******** 01111111)

      单字节、双字节的区分通过高字节高位区分,单字节高位为0,双字节的高字节高位为1。
  5. UTF-8
    1. 可变长字符编码,是unicode码的具体实现,UTF-8用1到6个字节编码Unicode字符。

      UTF-8编码规则:如果只有一个字节则其最高二进制位为0;如果是多字节,其第一个字节从最高位开始,连续的二进制位值为1的个数决定了其编码的字节数,其余各字节均以10开头。

      1字节 0xxxxxxx

      2字节 110xxxxx 10xxxxxx

      3字节 1110xxxx 10xxxxxx 10xxxxxx

      4字节 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx

      5字节 111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx

      6字节 1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
  6. 明白上述GBK和UTF-8的编码规则,我们再分析一下,单个中文字符是乱码,两个字符却能正常显示的问题。
    1. “你”
    2. UTF-8编码对应的二进制:11100100 10111101 10100000
    3. 将上述二进制通过GBK进行解码,根据GBK规则,第一个字节高位为1,使用双字节编码,

      “11100100 10111101”解码成“浣”,“10100000”对于GBK来说是非法的,就解码成了一种特殊字符“�”。

    4. 看看能不能将“浣�”还原回“你”呢?
    5. GBK编码对应的二进制:11100100 10111101 00111111
    6. 看到上述的二进制,根本不符合UTF-8编码规则,故用UTF-8进行解码,是解码成了一些特殊字符“�?”。
    7. 对于上述情况可以看出,一个二进制,如果不符合当前的编码规则,会被解码成特殊字符,但此特殊字符再进行编码,是回不到最初的二进制的
  7. 用同样的方式,分析“你好”为什么最终可以正常显示。
    1. “你好”
    2. UTF-8编码对应的二进制:11100100 10111101 10100000 11100101 10100101 10111101
    3. 将上述二进制通过GBK进行编码,根据GBK规则,使用双字节编码,“1100100 10111101”解码成“浣”,“10100000 11100101”解码成“犲”,“10100101 10111101”解码成“ソ”。
    4. 看看能不能将“浣犲ソ”还原成“你好”呢?
    5. GBK 编码对应的二进制:11100100 10111101 10100000 11100101 10100101 10111101
    6. 可以看出二进制是可以被还原的,将此二进制通过UTF-8解码,肯定能变成“你好”
  8. 可以看出,一个字符串,通过UTF-8进行编码,再通过GBK进行解码,再将得到的字符串进行GBK编码,最后将得到的二进制通过UTF-8解码,能否还原到最初的字符串,在于UTF-8编码后得到的二进制,是否符合GBK的编码规则,如果符合,最终就可以还原,如果不符合,就不可还原。
  9. 总结
    1. 理论上说,用GBK编码,UTF-8解码的字符串是不能还原到最初的字符串的,因UTF-8编码规则的特殊性,GBK编出的二进制,是很难匹配上的。
    2. 理论上说,系统出现乱码,将乱码还原到最初的样子,上述UTF-8编码,GBK解码,这个有时是可以还原的,有时是还原不了的,要看UTF-8编码的二进制是否都能符合GBK的编码规则,但GBK编码,UTF-8解码,这个基本是条不归路。
    3. 但实际中,有一种情况,是100%可以将乱码还原成最初的字符串。就是任意编码格式编码,ISO-8859-1解码,这个主要因为ISO-8859-1是单字节编码,而且匹配所有单字节情况,乱码字符串总是可以还原到最初的二进制。

原文地址:https://www.cnblogs.com/jiangtao1218/p/10322011.html