锟斤拷?UTF

您所在的位置:网站首页 文字乱码怎么转换回来啊 锟斤拷?UTF

锟斤拷?UTF

2024-07-11 17:10| 来源: 网络整理| 查看: 265

作为一名程序员,肯定有被乱码困扰的时候,真到了百思不得其解的时候,就会觉得:英文程序员真幸福。

但其实只要明白编码之间的转换规律,其实乱码so easy~

 

我们知道,计算机存储数据都是2进制,就是0和1,那么这么多的字符就都需要有自己对应的0和1组成的序列,计算机将需要存储的字符转换成它们对应的01序列,然后就可以储存在电脑里了。

 

比如我们可以定义用8位2进制表示一个字符,“00000000”表示小写字母“a”,“00000001”表示小写字母“b”,那么计算机要存储“ab”的时候,其实在计算机里的存储的是“0000000000000001”,读取的时候先读取前8位,根据对应关系,可以解码出“a”,再读取后8位,又可以解码出“b”,这样就读出了当时写入的“ab”了。而我们定义的这种字符和二进制序列的对应关系,就可以称之为编码。我们如果需要将“ab”发送给别人,因为网络也是基于二进制,所以只要先约定好编码规则,就可以发送“0000000000000001”,然后对方根据约定的编码解码,就可以得到“ab”。现在是互联网的时代,我们经常需要和其他的计算机进行交互,一套编码系统还是比较复杂的,所以大家就需要约定统一的编码,这样的编码是大家都约定好的,就不用再去约定编码规则了~然而,为了满足各种不同的需求,人们还是制定了很多种编码,没有哪一种能全面替代其他编码,所以现在多种编码并存。通常这些编码都被大家所接受和熟知,所以现在不用再通信前商量编码的对应规则和细节,只需要告诉对方,我采用的是什么通用编码,彼此就能愉快地通信了。

 

所以乱码的本质就是:读取二进制的时候采用的编码和最初将字符转换成二进制时的编码不一致。

 

ps:编码有动词含义也有名词含义,名词含义就是一套字符和二进制序列之间的转换规则,动词含义是使用这种规则将字符转换成二进制序列。

 

好了,废话不多,直接上一段代码:

import java.io.UnsupportedEncodingException;      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转换成GBK:"+utf2GbkString);           String utf2Gbk2UtfString = new String(utf2GbkString.getBytes("GBK"),"UTF-8");           System.out.println("UTF-8转换成GBK再转成UTF-8:"+utf2Gbk2UtfString);       }   }  

 

因为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进行解码,就可得到最初的“我们是中国人”。

这种多余的转换有时候还是很有用的,比如ftp协议只支持ISO-8859-1编码,这个时候如果要传中文,只能先换成ISO-8859-1的乱码,ftp完成后,再转回UTF-8就又可以得到正常的中文了。

 

怎么样?编码转换是不是so easy?那该来点正经的了:

 

  import java.io.UnsupportedEncodingException;      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:锟斤拷锟斤拷锟斤拷锟叫癸拷锟斤拷

 

WTF??万恶的“锟斤拷”,相信不少人都见过。这里GBK转成UTF-8乱码好理解,但是再转回来怎么变成了“锟斤拷锟斤拷锟斤拷锟叫癸拷锟斤拷”,这似乎不科学。

这其实和UTF-8独特的编码方式有关,由于UTF-8需要对unicode字符进行编码,unicode字符集是一个几乎支持所有字符的字符集,为了表示这么庞大的字符集,UTF-8可能需要更多的二进制位来表示一个字符,同时为了不致使UTF-8编码太占存储空间,根据二八定律,UTF-8采用了一种可变长的编码方式,即将常用的字符编码成较短的序列,而不常用的字符用较长的序列表示,这样让编码占用更少存储空间的同时也保证了对庞大字符集的支持。

正式由于UTF-8采用的这种特别的变长编码方式,这一点和其他的编码很不一样。比如GBK固定用两个字节来表示汉字,一个字节来表示英文和其他符号。

来测试一下:

import java.io.UnsupportedEncodingException;      public class EncodingTest {       public static void main(String[] args) throws UnsupportedEncodingException {           String srcString = "我们是中国人";           byte[] GbkBytes = srcString.getBytes("GBK");           System.out.println("GbkBytes.length:" + GbkBytes.length);           byte[] UtfBytes = srcString.getBytes("UTF-8");           System.out.println("UtfBytes.length:" + UtfBytes.length);           String s;           for (int i = 0; i 


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3