A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© supertoy 中级黑马   /  2014-8-13 15:56  /  3518 人查看  /  9 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

本帖最后由 supertoy 于 2014-8-14 09:30 编辑

gbk编码->iso8859-1解码->iso8859-1编码->gbk解码
但是【Gbk->utf8->utf8->gbk】就不可以?
毕老师说是因为utf8能识别汉字的问题。
但是还是不明白问题就经在哪里?
①【难道gbk编码后,iso8859-1针对生成每个字节能找到唯一的字符,然后唯一的字符又能返回到原来的编码吗】?
②【可以ISO8859-1解码出来的都是问号啊,如果在用ISO8859-1把生成的问号编码,怎么可能回到gbk编码的状态呢,怎么查表找到对应的编码?】
③【utf-8解码编码不行的原因,难道是如果查表不存在,就找一个固定的字符或者编码吗?所以不可回退吗?】
{:3_52:}


9 个回复

倒序浏览
关键是utf8是变长编码,它一个字符可能1-3个字节去编码。好了,原来人家GBK一个字符固定用两个字节,两个字符四个字节;到了utf-8,第一个字符它变成3个字节,第二个字符2个字节,成了5个字节,再转回GBK,两个字节编一个字符,怎么能回到原来?
回复 使用道具 举报
fantacyleo 发表于 2014-8-13 17:17
关键是utf8是变长编码,它一个字符可能1-3个字节去编码。好了,原来人家GBK一个字符固定用两个字节,两个 ...

gbk生成4个字节,如果utf-8既然能查表转成2个字符,为什么反查查不回4个字节呢?
【A1,A2,A4,A5】】=>【?,?】=>
既然能查出字符,肯定是根据编码表查出的
如果gbk的4个字节用utf8编码表查出的是2个字符,为什么这两个字符反推字节数就变了呢?{:3_62:}


回复 使用道具 举报
supertoy 发表于 2014-8-13 20:58
gbk生成4个字节,如果utf-8既然能查表转成2个字符,为什么反查查不回4个字节呢?
【A1,A2,A4,A5】】=>【? ...

问题是utf-8的两个字符是几个字节呢?2-6个字节都有可能。然后再反查gbk,你说怎么查?原来gbk一个字符用2字节表示是ab cd,到了utf-8如果变成3个字节,ab ef cd,请问gbk如何把这个ab ef cd转回ab cd?
回复 使用道具 举报
我认为utf8能识别汉字这个是中间环节,不是问题所在。问题是utf-8是三个字节表示一个字符,而欧洲字符集可以是因为一个字节表示一个字符,小于等于2就可以
回复 使用道具 举报
本帖最后由 supertoy 于 2014-8-13 21:41 编辑
fantacyleo 发表于 2014-8-13 21:20
问题是utf-8的两个字符是几个字节呢?2-6个字节都有可能。然后再反查gbk,你说怎么查?原来gbk一个字符 ...

假设byte[] bs = "abcd".getBytes("GBK") = 二个字节
那么这两个字节String s = new String(bs,"utf-8") = abefcd
byte[] bs2 = "abcde".getBytes("UTF-8") = 三个字节
没道理啊,原来是有2个字节utf8解码生成abcde,再abcde编码怎么会生成3个字节呢???
假设一个二个字节FFFF查出是a,反查a的编码难道不是FFFF吗?{:3_62:}
--------------------------------新的分割线----------------------------------------
------------------------------------------
【"哈哈"】=GBK=>【①字节数组】=>UTF8=>
                                                              【②??】
【"XX"】=GBK<=【③字节数组】<=UTF8<=
---------------------------
上面的逻辑有错误吗?
--------------------------
①能生成②
为什么②不能回到①呢?
-----------------------------
还是迷糊中...{:3_52:}
回复 使用道具 举报
icris 中级黑马 2014-8-13 22:04:18
7#
锟斤拷
http://baike.baidu.com/view/2638658.htm?fr=aladdin
回复 使用道具 举报
本帖最后由 fantacyleo 于 2014-8-13 22:11 编辑
supertoy 发表于 2014-8-13 21:40
假设byte[] bs = "abcd".getBytes("GBK") = 二个字节
那么这两个字节String s = new String(bs,"utf-8") ...

你没有仔细回味我一开始说的”utf-8是变长编码“这句话。gbk和iso8859不论识别得了还是识别不了,它们不会”搞破坏“,原来几个字节,我还还回去几个字节。原来字节是ab cd, 识别不了打印出??(iso8859)或?(gbk),可字节本身没变化。utf-8的编码长度是可变的,它进行编码转换时,可能在原来的字节中插入新字节,原来字节是ab cd,utf-8一转换就成了ab ef cd,原始字节被破坏了,当然就转不回去了。你的逻辑错误就在于假定字节数组1和字节数组3是相同的,但在utf8作用之下完全可能不同。而存在汉字时,就恰恰会发生这种不同——utf8的汉字编码是3个字节,而gbk是2个字节
回复 使用道具 举报
icris 中级黑马 2014-8-13 22:30:50
9#
http://www.fudan.edu.cn/new_dep/
iso8859-1 好用在哪,好用在它只要一个字节,一次读一个字节,查表显示,是什么就是什么,还有我们看是问号不一定就是问号,还可能是我们电脑没有装的语言,类似于你的手机把系统的字体换掉了,新字体没有那个字,就显示为口。
utf-8 为什么不好使,因为它往里面加东西换东西,它不用问号也不用口(用了问号和口…),用了写作 \xef\xbf\xbd 读作� 的一个东西,连着两个就是 �� \xef\xbf\xbd\xef\xbf\xbd ,这时候转 GBK 就能查表了,\xef\xbf 锟 \xbd\xef 斤 \xbf\xbd 拷
不知道那两个问号能不能显示
回复 使用道具 举报
本帖最后由 supertoy 于 2014-8-14 09:29 编辑

                String s = "哈哈";
                byte[] bytes = s.getBytes("gbk");
                System.out.println("GBK编码:"+ToHex.arrayToHex(bytes));
                s = new String(bytes,"utf-8");
                System.out.println("utf-8字符:"+s);
                bytes = s.getBytes("utf-8");
                System.out.println("UTF8编码:"+ToHex.arrayToHex(bytes));

-----------------
GBK编码:[b9(B:10111001),fe(B:11111110),b9(B:10111001),fe(B:11111110)]
utf-8字符:����
UTF8编码:UTF8编码:[ef,bf,bd,ef,bf,bd,ef,bf,bd,ef,bf,bd]
---------------------
utf8在对b9,fe,b9,fe,解码时【三个规则:(0),(110,10),(1110,10,10)】,无法找到匹配的字符,舍弃b9,用unicode占位符U+FFFD(ef,bf,bd)代替,
导致解码后无法还原原来的编码。{:3_52:}

回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马