论坛首页 入门技术论坛

理解并解决GBK转UTF-8奇数中文乱码

浏览 45409 次
该帖已经被评为新手帖
作者 正文
   发表时间:2011-06-21  
看不明白,这么多乱码
0 请登录后投票
   发表时间:2011-06-21  
经常碰到中文乱码的问题,每次都是瞎猫碰死耗子一样的乱试。看了这个有点明白,留后面慢慢体会。
0 请登录后投票
   发表时间:2011-06-21  
chenfeng0104 写道
arsenal04 写道
和刚看到的另两篇也是说编码的文章结合理解,有了一些收获,有个疑问,ISO-8859-1既然是单字节,那如果UTF-8转成字节数组占了3个字节,那是会转成3个字符吗?

是的,ISO-8859-1是一个字节表示一个字符,UTF-8是三个字节表示一个字符。

准确的说UTF-8表示中文时一般用3个字节
0 请登录后投票
   发表时间:2011-06-22  
原来是要先转为ISO-8859-1,收下了
0 请登录后投票
   发表时间:2011-06-22  
iceside 写道
..........

字符串编码迷思:

new String(input.getBytes("ISO-8859-1"), "GB18030")

上面这段代码代表什么?有人会说: “把input字符串从ISO-8859-1编码方式转换成GB18030编码方式”。如果这种说法正确,那么又如何解释我们刚提到的java字符串都采用unicode编码呢?

这种说法不仅是欠妥的,而且是大错特错的,让我们一一来分析,其实事实是这样的:我们本应该用GB18030的编码来读取数据并解码成字符串,但结果却采用了ISO-8859-1的编码,导致生成一个错误的字符串。要恢复,就要先把字符串恢复成原始字节数组,然后通过正确的编码GB18030再次解码成字符串(即把以GB18030编码的数据转成unicode的字符串)。注意,字符串永远都是unicode编码的。

但编码转换并不是负负得正那么简单,这里我们之所以可以正确地转换回来,是因为 ISO8859-1 是单字节编码,所以每个字节被按照原样 转换为 String ,也就是说,虽然这是一个错误的转换,但编码没有改变,所以我们仍然有机会把编码转换回来! 

 

总结:

所以,我们在处理java的编码问题时,要分清楚三个概念:Java采用的编码:unicodeJVM平台默认字符集和外部资源的编码。

 

这个地方是亮点

0 请登录后投票
   发表时间:2011-06-22   最后修改:2011-06-22
别误导人了: 前提你说了,你必须确保你的文件是GBK编码!
	String str = new String("我来了".getBytes("GBK"));
		byte[] bt = str.getBytes("UTF-8");
		System.out.println(bt.length);
		for(int i=0;i<bt.length;i++){
			System.out.print(bt[i]+"  ");
		}
		String str1 = new String(bt,"UTF-8");

		
		System.out.println(new String(str1.getBytes(),"GBK"));



0 请登录后投票
   发表时间:2011-06-22  
beykery 写道
楼主有一点说的不正确,utf-8是变长编码,有1个字节到4个字节编码的字符。

是1个到6个
0 请登录后投票
   发表时间:2011-06-22  
iceman1952 写道
beykery 写道
楼主有一点说的不正确,utf-8是变长编码,有1个字节到4个字节编码的字符。

是1个到6个

到底几个,到底几个,到底几个????
0 请登录后投票
   发表时间:2011-06-24  
iceman1952 写道
iceman1952 写道
beykery 写道
楼主有一点说的不正确,utf-8是变长编码,有1个字节到4个字节编码的字符。

是1个到6个

到底几个,到底几个,到底几个????

http://www.ietf.org/rfc/rfc3629.txt
0 请登录后投票
   发表时间:2011-09-30  
     String gbk = "我来了中过";//unicode
     byte gbkbytes[] = gbk.getBytes("GBK");//encode 成 GBK 字节
     String unicodeStr = new String(gbkbytes,"GBK"); // decode 成字符串(unicode)
    System.out.println("decode from gbk :"+unicodeStr);
    byte utf8bytes [] = unicodeStr.getBytes("utf-8"); // encode 成UTF-8编码的字节数组
    unicodeStr = new String (utf8bytes,"ISO-8859-1");
    System.out.println("decode from ISO-8859-1 会是乱码的:"+unicodeStr );
    unicodeStr = new String(unicodeStr.getBytes("ISO-8859-1"),"UTF-8");// encode 成UTF-8编码的字节数组

    System.out.println("decode from utf-8:"+unicodeStr); // decode 成字符串(unicode)

所以在java中字符串是不存在GBK,UTF-8编码之说的,在内存中都是unicode 编码的。所以从GBK字节编码的数组转换成UTF-8的字节编码的数组,需要字符串作为中间者。
所以根本不需要ISO-8859-1的介入:
    String gbk = "我来了中过";//unicode
    byte gbkbytes[] = gbk.getBytes("GBK");//encode 成 GBK 字节
    String unicodeStr = new String(gbkbytes,"GBK"); // decode 成字符串(unicode)
   System.out.println("decode from gbk :"+unicodeStr);
   byte utf8bytes [] = unicodeStr.getBytes("utf-8"); // encode 成UTF-8编码的字节数组
   unicodeStr = new String (utf8bytes,"utf-8");
   System.out.println("decode from utf-8:"+unicodeStr); // decode 成字符串(unicode)
0 请登录后投票
论坛首页 入门技术版

跳转论坛:
Global site tag (gtag.js) - Google Analytics