中文乱码的产生原因

先说一下什么叫乱码

不知道有没有人这样认为过,一个字符串不仅仅包含字符,还有隐藏着它的编码信息。比如java中String str = "你好";我之前是这样认为的,str这个字符串隐藏着它的编码方式unicode编码或者gbk、iso-8859-1等。这种理解是错误的,字符就是字符没有任何其他信息,正确的理解应该是,人在一个文件中所看到的字符串是系统经过把内存中的数码信息读取也再解码成一些字符最后显示,就是当你双击打开一个文本文件时系统会把内存的数码信息读取显示出来,当你保存一个文本文件时系统会把这个文件以你所设置的编码方式编码,再放进内存中。


所以说乱码也是一些字符,只是奇怪的字符而已,并没有什么”码“。

接着说乱码产生的原因

我们经常看到网上这样解释乱码原因:乱码是因为解码方式和编码方式不一致导致的,这句话本身没有错,但同样这句话的本身就是把乱码概括了而已,它并不能帮助你理解乱码。

所以我们要提的问题是:为什么解码方式和编码方式不一致会出现乱码。

这里以utf-8,gbk,iso-8859-1三种编码方式为例。 @Test

@Test
	 public void testEncode() throws Exception {
	    String str = "你好",en = "h?h";
	    
	    System.out.println("========中文字符utf-8=======");
	    byte[] utf8 = str.getBytes(); // 以utf-8方式编码 ,default:utf-8
	    for (byte b : utf8) {			
	    	System.out.print(b + "\t");
		}
	    
	    System.out.println("\n"+"========英文字符utf-8=======");
	    byte[] utf8_en = en.getBytes(); // 以utf-8方式编码 ,default:utf-8
	    for (byte b : utf8_en) {			
	    	System.out.print(b + "\t");
		}
	    
	    System.out.println("\n"+"========中文字符gbk=========");
	    byte[] gbk = str.getBytes("gbk");
	    for (byte b : gbk) {			
	    	System.out.print(b + "\t");
		}
	    
	    System.out.println("\n"+"========英文字符gbk=========");
	    byte[] gbk_en = en.getBytes("gbk");
	    for (byte b : gbk_en) {			
	    	System.out.print(b + "\t");
		}
	    
	    String s = new String(utf8,"utf-8");
	    String s1 = new String(utf8,"gbk");
	    System.out.println("\n"+s + "====gbk:" + s1);
	 }


测试上面方法,打印的结果是

========中文字符utf-8=======
-28 -67 -96 -27 -91 -67
========英文字符utf-8=======
104 63 104
========中文字符gbk=========
-60 -29 -70 -61
========英文字符gbk=========
104 63 104
你好====gbk:浣犲ソ

------------------------------------------------------------------------------------

可以得出结论:

一个中文字符以utf-8编码会转成3个byte,如果以gbk编码会转成2个byte;

一个英文字符以utf-8编码会转成1个byte,如果以gbk编码会转成1个byte。

从打印的最后一行结合29-31行代码可以看出,如果把byte数组utf8 以utf-8的方式解码不会有乱码,还是原来的”你好“,而如果以gbk方式解码则出现了三个乱码字符,为什么是3个而不是2个呢,6/2=3。

接下来说iso-8859-1,这种编码应用于英文系列,也就是说不能表示中文(如果要使用必须依赖于其它兼容iso-8859-1编码方式的编码),它读不懂的字符都将被视为英文问号'?',英文问号的iso-8859-1编码号是:63(十进制)(其实在几乎所有的编码方式中,所有英文字符都用1个固定的字节码表示,unicode编码除外)。

@Test
	 public void testISO() throws Exception {
		 String str = "你好";
		 byte[] bs = str.getBytes("iso-8859-1");
		 for (byte b : bs) {
			System.out.println(b);
		 }
		 System.out.println(new String(bs,"iso-8859-1"));
		 System.out.println(new String(bs,"utf-8"));
		 System.out.println(new String(bs,"gbk"));
		 System.out.println(new String(bs,"unicode"));		 
	 }
打印结果

63

63
??
??
??
㼿

说明63 =》?,所有中文都被认为是?,所以说当执行这句代码时:byte[] bs = "你好".getBytes("iso-8859-1");信息已丢失。

再执行String str = new String(bs,"任何charset");str已经不等于"你好"了,而是两个问号??。所以在tomcat中我们会经常遇上中文变为一长串??????,就是源于此。

在iso-8859-1、utf-8、gbk中一个字节码表示一个英文字符,

在unicode编码中一个字节码并不能表示任何字符,而且规定必须是两个字节码(有时4个)才能表示一个字符。


说了这么多,也许很多人会问为什么要用这么多编码方式,统一成utf-8不就能表示所有字符了?

编码不仅仅是要考虑是否能表示任何字符,还要考虑传输和存储。

1、utf-8确实几乎能表示所有已知字符。前面说过在utf-8编码中3个字节才表示一个中文字符,这样显然占空间,不利于传输和存储(传输和存储都是以二进制的方式进行的)

2、无疑一个字节表示一个字符最省空间,比如iso-8859-1。但这世上不是只有英文字符,还有各个地区国家的文字。所以字符的数量肯定是大于2的8次方的。

所以结合以上两点,就自然地出现了很多种编码方式。


了解各种编码方式的规则:https://jingyan.baidu.com/article/020278118741e91bcd9ce566.html

  • 5
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
mobar中文乱码可能是由于以下几种原因导致的: 1. 编码不匹配:mobar在处理中文字符时使用的编码方式与当前环境或文本的编码方式不一致。在处理中文时,常用的编码方式有UTF-8、GBK等,如果mobar使用的是UTF-8编码,而文本或环境使用的是GBK编码,就会出现乱码问题。 2. 字符集不支持:mobar所使用的字符集不支持中文字符,导致中文字符无法正确显示。一些较旧或较简单的字符集可能没有包含中文字符,因此在使用这些字符集的情况下,就会出现中文乱码。 3. 字符集转换错误:在进行字符集转换时,如果转换的过程出现错误或不兼容,也会导致中文乱码。例如,当尝试将一个GBK编码的文本转换为UTF-8编码时,如果转换过程中发生错误,就会产生乱码。 解决mobar中文乱码问题的方法有: 1. 确认mobar使用的编码方式和环境或文本的编码方式是否一致,如果不一致,则调整mobar的编码方式或使用合适的文本和环境编码方式。 2. 确认mobar所使用的字符集是否支持中文字符,如果不支持,则尝试更换字符集或升级mobar版本以支持中文字符。 3. 检查字符集转换的过程是否正确,可以使用专门的工具或库来进行字符集转换,确保转换的准确性和兼容性。 总之,解决mobar中文乱码问题需要确定编码方式、字符集和字符集转换的准确性,确保各个环节的匹配和正确性。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值