【Python】文本编码与chardet模块

简介

以前一直对字符编码很模糊,感觉编码方式有很多,在网上查资料也总是看的晕头转向,所以在这里先将几种常见的编码方式的关系总结一下。
常见的字符编码——ASCIIUnicodeGBKUTF-8

  • ASCII

ASCII编码的全称是American Standard Code for Information Interchange,美国信息互换标准代码。这是一种最早的、只用来保存英文文字的编码方式。ASCII编码方式只使用了1个字节(8比特位,可以组合出256种不同的状态)中0~127种组合存储了英文的文字。

  • GBK

当计算机普及到国内时,因为汉字的常用字就有将近6000个,使用ASCII编码已经完全不能满足使用的需求了。
所以在1981年,国家标准总局发布了GB2312(中国国家标准简体中文字符集),使用2个字节的组合,当两个大于127的字符连在一起时,就表示一个汉字,这样就组合出了7000多个简体字。
后来因为汉字的扩展需求,发布了GBK标准,K是扩展一次汉语拼音的声母。即不再要求第二个字节大于127,只要第一个字节大于127,则表示这是一个汉字的开始。这样共收录了将近22000个汉字和符号。且兼容了GB2312标准。
2005年时修订了GB18030标准,支持了国内少数民族的文字,共收录汉字70000余个。兼容了GBK标准。

  • Unicode

就如国内定义了GB2312标准一样,当时各个国家都规定了适用于自己语言的一套编码方式。但是这就导致各国相互之间谁也不懂谁的编码,装错字符系统就会导致显示全是乱码。
所以这时ISO(International Standards Organization,国际标准化组织)推出了Unicode标准用以解决这个问题。
Unicode标识以2个字节长度的数字来标识所有字符,除了英文以外的字符全部重新进行了统一编码。
注意Unicode只是一种标准,不是编码方式,给予了每个字符一个16比特位的数字标识,至于这个字符在内存中是由几个字节存储,并不是Unicode标准规定的。

  • UTF-8

Unicode标准制定后,在很长的一段时间内无法推广,直到互联网的普及,强烈要求出现一种统一的编码方式。然后就诞生了UTF-8,这个使用Unicode标准的编码方式。
注意:因此,UTF-8是Unicode标准的一种实现方式

UTF-8的编码规则很简单,只有两条:

  1. 对于单字节的符号,字节的第一位设为0,后面7位为这个符号的 Unicode 码。因此对于英语字母,UTF-8 编码和ASCII码是相同的
  2. 对于n字节的符号(n > 1),第一个字节的前n位都设为1,第n + 1位设为0,后面字节的前两位一律设为10。剩下的没有提及的二进制位,全部为这个符号的 Unicode 码。

下表为编码规则,字母x表示可用编码的位。

Unicode符号范围 UTF-8编码方式(二进制)
0000 0000-0000 007F 0xxxxxxx
0000 0080-0000 07FF 110xxxxx 10xxxxxx
0000 0800-0000 FFFF 1110xxxx 10xxxxxx 10xxxxxx
0001 0000-0010 FFFF 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx


以汉字为例,演示如何实现UTF-8编码:

的Unicode码是4E25100111000100101),根据上表,可以发现4E25处在第三行的范围内(0000 0800 - 0000 FFFF),因此的 UTF-8 编码需要三个字节,即格式是1110xxxx 10xxxxxx 10xxxxxx。然后,从的最后一个二进制位开始,依次从后向前填入格式中的x,多出的位补0。这样就得到了,的 UTF-8 编码是11100100 10111000 10100101,转换成十六进制就是E4B8A5

由此可见,汉字的Unicode码和UTF-8编码是不同的,它们之间可以通过规则进行转换

注意 : 汉字的Unicode码是2个字节,而UTF-8码是3个字节


Python 中的编码方式转换

Python3中的字符序列类型有两种:strbytes

bytes对象是一串十六进制格式字符序列,如b'\xe6\x88\x91',前方的b标示这串字符是bytes对象。

将bytes对象通过上述的某种编码方式可以解析为字符串,如将b'\xe6\x88\x91'使用UTF-8编码方式解码得到汉字,而使用GBK编码方式解码无法得到完整的汉字。

Python3中使用encode()decode()进行字符与二进制序列之间的转换,可以这样理解:
encode(编码)就是把人能看懂的汉字,转换为机器能看懂的二进制序列。
decode(解码)就是把人看不懂的二进制序列,转换为汉字。

使用encode()decode()时,有个encoding参数,默认值为UTF-8,指定了对字符串进行编码或解码时,使用的编码方式。


有关文件的编码方式

前面说了那么多,还没有讲到有关文件的编码方式,而且可能平时使用open()打开文件read()的时候,并没有指定编码方式,也能够正常打印出来文件的内容。

文件的编码方式是在open()是指定的,有个encoding参数,作用和字符串解码一样,如果以非二进制模式(b)打开文件,会默认通过UTF-8方式打开。

所以一份GBK编码的文件,如果不以二进制模式打开、且不设置这个encoding参数,是会报解码错误的(UnicodeDecodeError)。

当然,如果以二进制模式打开文件,再读取到的文本就已经是二进制序列了,不涉及encode问题,而是该以什么解码方式将二进制序列转换为人可以读懂的汉字。

所以对于一个未知编码方式的文件,如何通过代码获取其编码方式,然后转换为我们所期望的编码方式呢?
Python提供了一个第三方库chardet,是char detect的缩写,字符监测。
将二进制序列传入chardet.detect()方法,然后会返回一个字典。该字典有3个键值。

{
    'encoding': 'GB2312',
    'confidence': 0.99,
    'language': 'Chinese'
}

encoding是所识别出来该二进制序列的编码方式。
confidence是所识别出来的encoding正确概率(1.0表示100%)。
language是该编码方式适用的语言。
可以根据confidence概率决定是否使用encoding编码方式。

你可能感兴趣的:(【Python】文本编码与chardet模块)