网站优化的,wordpress显示轮播图,搭建网站不用服务器吗,硅谷网站开发薪酬作为一名程序员#xff0c;肯定有被乱码困扰的时候#xff0c;真到了百思不得其解的时候#xff0c;就会觉得#xff1a;英文程序员真幸福。但其实只要明白编码之间的转换规律#xff0c;其实乱码还是很好解决的。我们都知道字符串在保存和传输的时候需要先经过编码成二进… 作为一名程序员肯定有被乱码困扰的时候真到了百思不得其解的时候就会觉得英文程序员真幸福。但其实只要明白编码之间的转换规律其实乱码还是很好解决的。我们都知道字符串在保存和传输的时候需要先经过编码成二进制到达目的地后再进行解码。所以乱码的本质就是读取二进制的时候采用的编码和最初将字符转换成二进制时的编码不一致。 ps编码有动词含义也有名词含义名词含义就是一套字符和二进制序列之间的转换规则动词含义是使用这种规则将字符转换成二进制序列。比如我们通常使用下面代码处理get请求中的中文乱码String s1 new String(s.getBytes(iso8859-1), utf-8);这是由于编码的时候使用的是utf-8而解码的时候使用的是iso8859-1那么当然会出现乱码这时将得到的字符串使用iso8859-1编码就可以得到原始编码然后再使用utf-8进行解码就能得到正确的字符。再看一段代码public class EncodingTest {public static void main(String[] args) throws UnsupportedEncodingException {String srcString 我们是中国人;String utf2GbkString new String(srcString.getBytes(UTF-8),GBK);System.out.println(UTF-8转换成GBKutf2GbkString);String utf2Gbk2UtfString new String(utf2GbkString.getBytes(GBK),UTF-8);System.out.println(UTF-8转换成GBK再转成UTF-8utf2Gbk2UtfString);}
}因为UTF-8和GBK是两套中文支持较好的编码所以经常会进行它们之间的转换这里就以它们举例。以上代码运行打印出以下内容UTF-8转换成GBK鎴戜滑鏄腑鍥戒汉UTF-8转换成GBK再转成UTF-8我们是中国人我们看到将我们是中国人以UTF-8编码转换成byte数组byte数组其实就相当于二进制序列了此过程即编码再以GBK编码和byte数组创建新的字符串此过程即以GBK编码去解码byte数组得到字符串就产生乱码了。因为编码采用的UTF-8和解码采用的GBk不是同一种编码所以最后结果乱码了。之后再对乱码使用GBK编码还原到解码前的byte数组再使用和最初编码时使用的一致的编码UTF-8进行解码就可得到最初的“我们是中国人”。这个例子和上边get请求产生乱码类似。有时候这种编码转换并不会奏效看下面代码public class EncodingTest { public static void main(String[] args) throws UnsupportedEncodingException { String srcString 我们是中国人; String gbk2UtfString new String(srcString.getBytes(GBK), UTF-8); System.out.println(GBK转换成UTF-8 gbk2UtfString); String gbk2Utf2GbkString new String(gbk2UtfString.getBytes(UTF-8), GBK); System.out.println(GBK转换成UTF-8再转成GBK gbk2Utf2GbkString); }
}这次我们反过来先将字符串以GBK编码再以UTF-8解码再以UTF-8编码再以GBK解码。这次的运行结果是GBK转换成UTF-8йGBK转换成UTF-8再转成GBK锟斤拷锟斤拷锟斤拷锟叫癸拷锟斤拷万恶的“锟斤拷”相信不少人都见过。这里GBK转成UTF-8乱码好理解但是再转回来怎么变成了“锟斤拷锟斤拷锟斤拷锟叫癸拷锟斤拷”这似乎不科学。这其实和UTF-8独特的编码方式有关由于UTF-8需要对unicode字符进行编码unicode字符集是一个几乎支持所有字符的字符集为了表示这么庞大的字符集UTF-8可能需要更多的二进制位来表示一个字符同时为了不致是UTF-8编码太占存储空间根据二八定律UTF-8采用了一种可变长的编码方式即将常用的字符编码编码成较短的序列而不常用的字符用较长的序列表示这样让编码占用更少的存储空间的同时也保证了对庞大字符集的支持。正式由于UTF-8采用的这种特别的变长编码方式这一点和其他的编码很不一样。比如GBK固定用两个字节来表示汉字一个字节来表示英文和其他符号。而utf-8采用的是一种变长的编码方案从一个字节到四个字节不等而上文中的中文是使用的三个字节代表一个字符。UTF-8编码的读取方式也比较不同需要先读取第一个字节然后根据这个字节的值才能判断这个字节所表示的字符共需要多少字节来表示。对于某一个字符的UTF-8编码如果只有一个字节则其最高二进制位为0如果是多字节其第一个字节从最高位开始连续的二进制位值为1的个数决定了其编码的位数其余各字节均以10开头。UTF-8最多可用到6个字节。 所以当我们将由GBK编码的12个字节试图用UTF-8解码时会出现错误由于GBK编码出了不可能出现在UTF-8编码中出现的序列所以当我们试图用UTF-8去解码时经常会遇到这种不可能序列对于这种不可能序列UTF-8把它们转换成某种不可言喻的字符“”当这种不可言喻的字符再次以UTF-8进行编码时他们已经无法回到最初的样子了因为那些是UTF-8编码不可能编出的序列。然后这个神秘字符再转换成GBK编码时就变成了“锟斤拷”。当然还有很多其他的巧合可能正好碰到UTF-8中存在的序列甚至原本不是一个字符的字节可能是某个字的第二个字节和下一个字的两个字节正好被识别成一个UTF-8序列于是解码出一个汉字当然这些在我们看来都是乱码了只不过不是“锟斤拷”的样子。因为不可能序列更普遍存在所以GBK转UTF-8再转GBK时最常见的便是“锟斤拷”所以以非UTF-8编码编码出的字节数组一旦以UTF-8进行解码通常这是一条不归路再尝试将解码出的字符以UTF-8进行编码也无法还原之前的字节数组。相反地其他的固定长度编码几乎都可以顺利还原。 转载于:https://blog.51cto.com/a4boy/1889996