常见的编码
ASCII: 美国人发明的,只编码英文字母和符号,1个字节。
GB2312: 中国人发明的,增加了中文汉字和符号,2个字节。
Unicode: 为了把所有语言都统一到一套编码里,一般是2个字节,生僻字4个字节。
UTF-8: 为了节省英文字符内存空间,UTF-8可变长编码,常用的英文字母被编码成1个字节,汉字通常是3个字节,生僻的字符编码成4-6个字节。
1 >>> S = '中文' 2 >>> print type(S), len(S) 3 <type 'str'> 4 4 5 >>> unicodeS = u'中文' 6 >>> print type(unicodeS), len(unicodeS) 7 <type 'unicode'> 2 8 9 >>> utfS = u'中文'.encode('utf-8') 10 >>> print type(utfS), len(utfS) 11 <type 'str'> 6
在计算机内存中,统一使用Unicode编码,当需要保存到硬盘或者需要传输的时候,就转换为UTF-8编码,这样可以节省很多存储空间。
其中,python2和python3系统默认编码分别是ascii和utf-8,以python2.7为例:
1 >>> import sys 2 >>> sys.getdefaultencoding() 3 'ascii' 4 5 >>> a = 'hello' 6 >>> print type(a) 7 <type 'str'> 8 >>> b = a.decode('ascii') 9 >>> print type(b) 10 <type 'unicode'> 11 >>> c = a.decode('ascii').encode('utf-8') 12 >>> print type(c) 13 <type 'str'>
然而python2.7中,比较麻烦的还是有两种数据模型来支持字符串这种数据类型,str和unicode(python3改进后只有unicode一种),比如
s = '中文'
就是str类型的字符串,而u=u"中文"
就是一个unicode类型的字符串。unicode是由str类型的字符串解码后得到,unicode也可以编码成str类型。即
str --> decode -->unicode
unicode --> encode --> str
在做编码转换时,通常需要以unicode作为中间编码,即先将其他编码的字符串解码(decode)成unicode,再从unicode编码(encode)成另一种编码。
注:Unicode 格式:像u0000;二进制编码 格式:像x00x00,其中utf-8,gbk就是二进制编码;
1 >>> s1 = u'中文' 2 >>> type(s1) 3 <type 'unicode'> 4 >>> s2 = 'ABC' 5 >>> type(s2) 6 <type 'str'> 7 8 #字符串转码成unicode对象 9 >>> u'ABC' 10 u'ABC' 11 >>> u'中文' 12 u'u4e2du6587' 13 14 #英文字符串编码成utf8格式 15 >>> 'ABC'.encode('utf-8') 16 'ABC' 17 >>> u'ABC'.encode('utf-8') 18 'ABC' 19 20 #中文字符串需先转码成unicode,再编码成utf8格式 21 >>> '中文'.encode('utf-8') 22 23 Traceback (most recent call last): 24 File "<pyshell#15>", line 1, in <module> 25 '中文'.encode('utf-8') 26 UnicodeDecodeError: 'utf8' codec can't decode byte 0xd6 in position 0: invalid continuation byte 27 28 >>> u'中文'.encode('utf-8') 29 'xe4xb8xadxe6x96x87' 30 >>> u'u4e2du6587'.encode('utf-8') 31 'xe4xb8xadxe6x96x87' 32 33 #字符串从utf8格式解码成unicode 34 >>> 'ABC'.decode('utf-8') 35 u'ABC' 36 >>> 'xe4xb8xadxe6x96x87'.decode('utf-8') 37 u'u4e2du6587' 38 >>> print 'xe4xb8xadxe6x96x87'.decode('utf-8') 39 中文
编码检验和转换
1 #检查编码 2 >>> import urllib 3 >>> rawdata = urllib.urlopen('http://www.google.cn/').read() 4 >>> import chardet 5 >>> chardet.detect(rawdata) 6 {'confidence': 0.99, 'encoding': 'utf-8'} 7 8 #将String对象从UTF-8内码转换为gbk,相反则s.decode('gbk').encode('utf-8') 9 >>> rawdata.decode('utf-8').encode('gbk') 10 11 #以unicode为中介实现编码或解码 12 >>> u'中文'.encode('gbk') 13 'xd6xd0xcexc4' 14 >>> u'中文'.encode('utf-8') 15 'xe4xb8xadxe6x96x87' 16 >>> 'xd6xd0xcexc4'.decode('gbk') 17 u'u4e2du6587' 18 >>> print u'u4e2du6587' 19 中文 20 >>> 'xe4xb8xadxe6x96x87'.decode('utf-8') 21 u'u4e2du6587' 22 >>> print u'u4e2du6587' 23 中文
其中,decode的函数原型是 decode([encoding], [errors='strict']),可以用第二个参数控制错误处理的策略。
默认的参数就是strict,代表遇到非法字符时抛出异常;
如果设置为ignore,则会忽略非法字符;
如果设置为replace,则会用?取代非法字符;
读写文件编码
以test.txt文件为例,文件内容为“测试”。
1 >>> #coding=utf-8 2 >>> f = open("test.txt") 3 >>> s = f.read() 4 >>> print type(s) 5 <type 'str'> 6 >>> s 7 'xb2xe2xcaxd4' 8 >>> u = s.decode("gbk") 9 >>> u 10 u'u6d4bu8bd5' 11 >>> f.write(u.encode("utf-8")) 12 >>> print u 13 测试