Chinaunix首页 | 论坛 | 博客
  • 博客访问: 197068
  • 博文数量: 40
  • 博客积分: 2265
  • 博客等级: 大尉
  • 技术积分: 434
  • 用 户 组: 普通用户
  • 注册时间: 2010-08-23 17:01
文章分类

全部博文(40)

文章存档

2014年(1)

2013年(2)

2012年(6)

2011年(5)

2010年(26)

我的朋友

分类: Python/Ruby

2010-09-02 12:19:53

对应中国人来说字符集的相互转换真是麻烦,搞不好就是大串的乱码,实在有必要多多复习一下基本概念!!
ISO8859-1,通常叫做Latin-1。Latin-1包括了书写所有西方欧洲语言不可缺少的附加字符。而gb2312是标准中文字符集。
UTF-8 是 UNICODE 的一种变长字符编码,即 RFC 3629。简单的说——大字符集。可以解决多种语言文本显示问题,从而实现应用国际化和本地化。
对系统来讲,UTF-8 编码可以通过屏蔽位和移位操作快速读写,排序更加容易。UTF-8 是字节顺序无关的,它的字节顺序在所有系统中都是一样的。因此 UTF-8 具有更高的性能。
在chinaunix看到篇实例讲解,很是直观,下面就贴出来,与大家共享!!

python 代码

1. >>> a = "我"
2. >>> b = unicode(a,"gb2312")
3. >>> a.__class__
4. 'str'>
5. >>> b.__class__
6. 'unicode'>
7. >>>

看出来了吧,两种字符串。
再来
python 代码

1. >>> a
2. '\xce\xd2'
3. >>> b
4. u'\u6211'

变量a是两个字符,b是一个unicode字符。
关于这两种字符串,Python文档-->LanguageReference-->DataModel-->The standard type hierarchy-->
Sequences,有一些Strings,Unicode的描述。
至于
python 代码

1. >>> z = u"我"
2. >>> #这种代码,其实什么都不是。
3. >>> z.__class__
4. 'unicode'>
5. >>> z
6. u'\xce\xd2'

看到了吧,这个奇怪的东西......
后来在WindowsXP、纯python命令行下试过,得出的结论不同,z的结果变成了u'\u6211',这里完全不应
该在pyshell下作试验的,看来还有很多问题尚未理解清楚

再来看看encode,decode
什么情况用encode,什么情况又是decode呢,刚开始总是被搞昏。其实各种本地字符集的英文名是
Coded Character Set,要转换为Coded,肯定是要encode了,同样,从里面解出来也应该叫decode……

decode就是把其他编码转换为unicode,等同于unicode函数;encode就是把unicode编码的字符串转换

特定编码。在pyshell里继续:
a是Str类型的,所以再用encode会报错。用print输出时会调用默认编码转换为系统编码?

python 代码

1. >>> a.decode("gb2312")
2. u'\u6211'
3. >>> print a.decode("gb2312")
4. 我
5. >>> a.encode("gb2312")
6. Traceback (most recent call last):
7. File "", line 1, in ?
8. UnicodeDecodeError: 'ascii' codec can't decode byte 0xce in position 0: ordinal not in range(128)

b是unicode类型,打印时需要先encode(编码)成系统编码
python 代码

1. >>> print b.encode("gb2312")
2. 我
3. >>> b.encode("gb2312")
4. '\xce\xd2'
5. >>> b.decode("gb2312")
6. Traceback (most recent call last):
7. File "", line 1, in ?
8. UnicodeEncodeError: 'ascii' codec can't encode character u'\u6211' in position 0: ordinal not in
range(128

字符串内码的转换,是开发中经常遇到的问题。
在Java中,我们可以先对某个String调用getByte(),由结果生成新String的办法来转码,也可以用NIO包里面的Charset来实现。
在Python中,可以对String调用decode和encode方法来实现转码。
比如,若要将某个String对象s从gbk内码转换为UTF-8,可以如下操作
s.decode(‘gbk’).encode(‘utf-8′)

可是,在实际开发中,我发现,这种办法经常会出现异常:
UnicodeDecodeError: ‘gbk’ codec can’t decode bytes in position 30664-30665: illegal multibyte sequence

这是因为遇到了非法字符——尤其是在某些用C/C++编写的程序中,全角空格往往有多种不同的实现方式,比如\xa3\xa0,或者\xa4 \x57,这 些字符,看起来都是全角空格,但它们并不是“合法”的全角空格(真正的全角空格是\xa1\xa1),因此在转码的过程中出现了异常。

这样的问题很让人头疼,因为只要字符串中出现了一个非法字符,整个字符串——有时候,就是整篇文章——就都无法转码。

幸运的是,tiny找到了完美的解决办法(我因此被批评看文档不仔细,汗啊……)
s.decode(‘gbk’, ‘ignore’).encode(‘utf-8′)

因为decode的函数原型是decode([encoding], [errors='strict']),可以用第二个参数控制错误处理的策略,默认的参数就是strict,代表遇到非法字符时抛出异常;
如果设置为ignore,则会忽略非法字符;
如果设置为replace,则会用?取代非法字符;
如果设置为xmlcharrefreplace,则使用XML的字符引用。

阅读(740) | 评论(0) | 转发(0) |
0

上一篇:爬虫的设计

下一篇:cookielib模块整理

给主人留下些什么吧!~~