编码问题,关于gb2312和utf-8

zhuanshen712 2011-05-24 11:47:27
加精
相信大家很多人跟我一样,对于编码一直感觉云山雾罩,说知道吧?就知道gb2312是中文编码,一看见乱码,就知道是编码出了问题,但是是哪儿出问题,为什么出问题,除了蒙,还是蒙。尤其是弄好了之后,有人问:为什么呢。自己也不知道,就说:反正就是这样的,用什么编码就用什么解码。为什么,鬼知道。
其实问题还是理解了之后,才能真正的明白为什么会这样,而且编码这个问题,也不是那么深奥,在网上搜索了一些资料,算是一直以来对编码问题的一个解决吧,最让人明白的资料有两个,第一个:
http://www.cnblogs.com/KevinYang/archive/2010/06/18/1760597.html
这个关于编码,我认为是最清楚的了,刚开始看完之后,觉得自己是真明白了,gb2312只是一个字符集,而unicode是所有能用到的字符的一个总集,utf-8是一种编码。它的字符集就是unicode。而且unicode是全人类达成共识的巨大的字符集,包括了gb2312字符集。
有了这个“底气”之后,就开始了自己的探索了:
1、用记事本一个写一个xml,如下:

<?xml version="1.0" encoding="gb2312"?>
<root>
<person>hi,大 美女你好</person>
</root>

将这个记事本保存为utf-8格式,然后打开,乱码,想也没想,感觉就是:用utf-8编码的文件,用gb2312的去解码,有的utf-8字符gb2312都没有,肯定会出问题了。。。(这个理解是错误的!!!)
2、用记事本一个写一个xml,如下:

<?xml version="1.0" encoding="utf-8"?>
<root>
<person>hi,大 美女你好</person>
</root>

将这个记事本保存为ansi格式(在简体中文的操作系统下,就是gb2312编码),然后打开,乱码???为什么呢?unicode编码不是包含了gb2312的字符集吗?按说应该能解析啊???(延续了第一个的想法,仅仅以字符集的大小去判断,还是错误的)
没办法,只能继续网上找答案了,于是第二个资料出现了。
http://social.msdn.microsoft.com/Forums/zh-CN/2212/thread/f656ec85-2cd0-4d6a-a207-fe30523cc5a4/
对于这个问题是这样说的:“UTF-8中包含所有 gb2312 中的字符的定义 但是 每个字符的编号却不是完全对应 的 所以就会出现页面的中文字不能对应 的情况”
答案详见4楼Raymond Tang 版主的答案。
这样的话,就可以解释了为什么utf-8解析不了gb2312中的字符了。
但是,我觉得这个答案还是有问题,像Raymond Tang版主所说,“每个字符的编号却不是完全对应 的”,他的意思,应该是gb2312中的编码和utf-8的编码编号是不一样的,所以不能解析出正确的字符。而如果仅仅是编码不一样,那至少也不会变化太大,应该是差不多还是个汉字吧?为啥成乱码呢?
于是,我又仔细看了看第一篇文章,感觉发现了问题的所在:“GB2312以及GBK字符集,限定了使用最多2个字节来编码所有字符,并且规定了字节序。这样的编码系统通常用简单的查表,也就是通过代码页就可以直接将字符映射为存储设备上的字节流了。”,而:“虽然每个字符在Unicode字符集中都能找到唯一确定的编号(字符码,又称Unicode码),但是决定最终字节流的却是具体的字符编码”,这时,就由utf-8来决定了。简单的来说,就是字符流被打乱了,utf-8是变长编码的,它不能按照gb2312那样解析字节流。所以出现了乱码。
所以,终归到底,unicode是包含了gb2312中的字符集,但是每种编码解码方式不一样,也就是说,utf-8编码是一种规则,他自己编码的字节流,需要用自己的规则去解码,如果不一致,就会出现乱码情况。这就是根源所在。

期间还发现了个挺有趣的事情:当新建文本文档只输入“联通”2字保存再打开时将是乱码。
详见:http://baike.baidu.com/view/1273097.htm

这个帖子是我自己的一个总结,以备啥时候忘了能提醒自己,同时希望能对像我一样不明白的一些童鞋有些帮助,让那些早就深刻理解这些东西的人来说见笑了。。。
如果我理解的还是有什么偏差,希望大家能够指正。谢谢。
...全文
14289 245 打赏 收藏 转发到动态 举报
写回复
用AI写文章
245 条回复
切换为时间正序
请发表友善的回复…
发表回复
xiaoqiangailulu 2011-09-16
  • 打赏
  • 举报
回复
领教了啊 加油
gaozhlzh 2011-09-16
  • 打赏
  • 举报
回复
mark下
adandelion 2011-07-12
  • 打赏
  • 举报
回复
good
dinghun8leech 2011-06-09
  • 打赏
  • 举报
回复
多谢分享。
懒得搭理你 2011-06-09
  • 打赏
  • 举报
回复
杯具的“联通”
tiantianmazht 2011-06-09
  • 打赏
  • 举报
回复
学习了
Chen_j_m 2011-06-08
  • 打赏
  • 举报
回复
曾经被编码折腾过很久
曾经的纠结,留做备用
redleaves 2011-06-08
  • 打赏
  • 举报
回复
不同的编码方案是不同时期,不同组织按不同的技术要求设计的特定的解决方案.它们中间本身是没有直接联系的.
最早期,只有英文字符的时候就英文本身都有很多不同的编码.后来逐渐统一使用ASCII做为标准编码(注意:这里说的编码是指给特定的字符分配一个数字编号)
后来,因为本地化的需要,各国组织分别设计了用于显示本国字符的编码.用于中文的编码,最出名的就是gb2312.它把收录的几千个中文字符分区,每个字符分配唯一的一个区位码.由于中文数量太多,1个byte远远不够.于是,就在ASCII中,选取了高位的一部分不常用字符做前缀,使用2个字节表示一个中文字符,从而建立起了到区位码的映射关系.这里的映射过程是对中文编码的再一次编码.后来的GBK在这个基础上对字符数量做了进一步扩充.但原理是相同的.
由于各地的本地编码互不兼容,为了统一字符编码成立了UNICODE的组织.它使用16位数表示一个字符.并保证了与ASCII中低位字符的编码一致性.但同一个中文字符在UNICODE中的编码和在GB2312中的编码是不同的.所以GB2312/GBK和UNICODE互转是要用专门的工具进行字符映射才行的.
随着计算机的发展,越来越多的语言/字符要被数字化.早期的UNICODE已经不能满足这些需要了.于是又出现了UCS-4的编码.它定义了一套32位的字符编码,并把32位的编码空间分成了很多组16位字符页,其中第0组0号字符页是BMP,BMP和旧的UNICODE完全兼容.
但32位的UCS字符编码和旧的ASCII及旧的UNICODE没法直接兼容,这样,很多现有的系统升级很困难,而且UCS-4中绝大多数的编码空间是空的,没有字符.直接用4字节来表示字符太浪费空间.于是,又发明了UTF-8/UTF-16等编码,用来表示UCS-4中的字符.
UTF-16使用完全兼容旧UNICODE的16位数字表示字符.如果遇到无法表示的字符,则使用多个16位数加前缀的形式进行编码.
UTF-8则是为了兼容ASCII设计的,它使用字节编码.保持0~127范围内的ASCII字符不变,128~255字符做前缀用多个字节表示一个字符.UTF-8中,一个字符可以是1~5个字节.字符的长度由前缀高位1的数量确定.
比如:
0xxxxxxx 是0~0x7F的基本ASCII字符
110xxxxx 10xxxxxx 就可以表示0x80~0x7FF
1110xxxx 10xxxxxx 10xxxxxx 表示0x800~0xFFFF
等等..
forwxj 2011-06-07
  • 打赏
  • 举报
回复
还真不懂,学习了!!
wanzhuan2010 2011-06-07
  • 打赏
  • 举报
回复
让我开始理解编码!
潞邊壹仦貓 2011-06-07
  • 打赏
  • 举报
回复
学习,确实不错。。。
asus52jr 2011-06-05
  • 打赏
  • 举报
回复
我也想弄清楚了!
airborne_troops 2011-06-04
  • 打赏
  • 举报
回复
我觉得从这个角度来讲,理解都是有问题的。

问题的关键其实不是在这里, 而是在文件保存的格式与你XML解析编码问题。

例:
<?xml version="1.0" encoding="utf-8"?>
<root>
<person>hi,大 美女你好</person>
</root>

如果你通过记事本是以UTF-8格式保存的话, 你打开肯定没有问题,是因为这个文件保存的时候字符都是以UTF-8的形式保存,使用IE打开的时候IE会读encoding的值,当读到是utf-8的时候,正好与你保存的值是一致的,所以IE能解析"hi,大 美女你好"这段字符。请记住一点,这里有两类编码:一是这个文件保存时的编码,另一个是你XML格式要求的编码。如果两者是一致的,解析出来的结果肯定就是你要的。

反过来也是一样的道理。

另外, gb2312根本就不是UNICODE编码格式,UNICODE是固定宽度的,但gb2312的时候你们会发现英文还是1个字节的,也就说明是MBCS(我们通常讲的ANSI格式)。
kgduwu 2011-06-04
  • 打赏
  • 举报
回复
学习. . .
qingyouzijuyi 2011-06-03
  • 打赏
  • 举报
回复
收藏学习了。
mzy939216 2011-06-03
  • 打赏
  • 举报
回复
学习了,谢谢楼主的总结,有时候真的意识不到这些问题!
qdujunjie 2011-06-03
  • 打赏
  • 举报
回复
傻×一个
xiaocongzhi 2011-06-03
  • 打赏
  • 举报
回复
AWesome,收藏,细细研究
agen76 2011-06-03
  • 打赏
  • 举报
回复
学习了
玉儿 2011-06-03
  • 打赏
  • 举报
回复
mark
加载更多回复(209)

110,534

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • Web++
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧