详解Python字符串编码格式

最早的字符串编码是美国标准信息交换码ASCII,仅对10个数字、26个大写英文字母、26个小写英文字母及一些其他符号进行了编码。ASCII采用1个字节来对字符进行编码,最多只能表示256个符号。

随着信息技术的发展和信息交换的需要,各国的文字都需要进行编码,不同的应用领域和场合对字符串编码的要求也略有不同,于是又分别设计了多种不同的编码格式,常见的主要有UTF-8UTF-16UTF-32GB2312GBKCP936base64CP437等等。UTF-8编码是国际通用的编码,以1个字节表示英语字符(兼容ASCII),以3个字节表示中文,还有些语言的符号使用2个字节(例如俄语和希腊语符号)或4个字节,UTF-8对全世界所有国家需要用到的字符进行了编码。

GB2312是我国制定的中文编码,使用1个字节表示英语,2个字节表示中文;GBK是GB2312的扩充,而CP936是微软在GBK基础上开发的编码方式。GB2312、GBK和CP936都是使用2个字节表示中文。

不同编码格式之间相差很大,采用不同的编码格式意味着不同的表示和存储形式,把同一字符存入文件时,写入的内容可能会不同,在理解其内容时必须了解编码规则并进行正确的解码。如果解码方法不正确就无法还原信息,从这个角度来讲,字符串编码也具有加密的效果

在本文的讨论中,包括本公众号里的绝大多数文章,都是基于Python 3.5.x的,整个Python社区都知道最迟到2020年Python就不再提供维护了,这个时间很可能会提前,要是还有人坚持抱着Python 2.7不放,可能很快就要吃亏的。

在Python 3.x中,字符串有关的类主要是strbytes,其中bytes是字节串类型。str对象使用encode()方法可以按指定的编码格式编码成为字节串,而bytes对象使用decode()方法并指定正确的编码格式进行解码即可还原为原来的str对象。

>>> '山东烟台'.encode() #默认使用utf8编码

b'\xe5\xb1\xb1\xe4\xb8\x9c\xe7\x83\x9f\xe5\x8f\xb0'

>>> _.decode() #默认使用utf8解码

'山东烟台'

>>> '山东烟台'.encode()

b'\xe5\xb1\xb1\xe4\xb8\x9c\xe7\x83\x9f\xe5\x8f\xb0'

>>> _.decode('gbk') #使用utf8编码再使用gbk解码的结果

'灞变笢鐑熷彴'

Python 3.x完全支持中文字符,默认使用UTF8编码格式,无论是一个数字、英文字母,还是一个汉字,都按一个字符对待和处理。例如在Python 3.5.2中执行下面的代码,从代码中可以看到,在Python 3.x中甚至可以使用中文作为变量名。

>>> import sys

>>> sys.getdefaultencoding() #查看默认编码格式

'utf-8'

>>> s = '中国山东烟台'

>>> len(s) #字符串长度,或者包含的字符个数

6

>>> s = 'SDIBT'

>>> len(s)

5

>>> s = '中国山东烟台abcde' #中文与英文字符同样对待,都算一个字符

>>> len(s)

11

>>> 姓名 = '董付国' #使用中文作为变量名

>>> 年龄 = 39

>>> print(姓名) #输出变量的值

董付国

>>> print(年龄)

39

这样的就引出了一个问题,文本文件中存放的是字符串信息,自然也有不同的编码格式,这样的话就需要在读写内容时使用正确的编码格式,使用gbk编码的文件无法通过utf8编码正常读写,除非里面全都是ASCII编码范围的字符。Python 3.x中用来打开文件的内置函数open()还提供了一个encoding参数用来指定文件的编码格式,默认使用cp936编码,例如:

>>> fp = open('test1.txt', 'r') #默认使用cp936

>>> fp

<_io.TextIOWrapper name='test1.txt' mode='r' encoding='cp936'>

>>> fp = open('test1.txt', 'r', encoding='utf8') #明确指定使用utf8

>>> fp

<_io.TextIOWrapper name='test1.txt' mode='r' encoding='utf8'>

至于如何读写文本文件内容,请参考我昨天发的文章:使用Python读写文本文件内容

最后一个问题来了,如果是自己生成的文本文件,当然是知道用的什么编码了,如果是别人生成的呢,有没有办法先判断一下使用的是什么编码然后再进行读写呢?强大的Python有个扩展库chardet就是专门用来做这个的。

>>> import chardet

>>> with open('test1.txt', 'rb') as fp:

result = chardet.detect(fp.read())

>>> result #结果的第一项是可信度,有时候可能不是特别准确

{'confidence': 1.0, 'encoding': 'ascii'}

>>> with open('111.txt', 'rb') as fp:

result = chardet.detect(fp.read())

>>> result

{'confidence': 0.73, 'encoding': 'windows-1252'}

>>> with open('222.txt', 'rb') as fp:

result = chardet.detect(fp.read())

>>> result['encoding']

'UTF-8-SIG'

原文发布于微信公众号 - Python小屋(Python_xiaowu)

原文发表时间:2016-11-28

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏Golang语言社区

《GO并发编程实战》—— 原子操作

我们已经知道,原子操作即是进行过程中不能被中断的操作。也就是说,针对某个值的原子操作在被进行的过程当中,CPU绝不会再去进行其它的针对该值的操作。无论这些其它的...

46670
来自专栏小白的技术客栈

Python内置数据结构之字典

今天给大家讲解Python内置数据结构:字典。字典的内容比较多,今天只是简单地介绍一下,明天会继续补充字典相关的内容。 关于Windows的环境安装及配置,小白...

32440
来自专栏葡萄城控件技术团队

5分钟掌握var,let和const异同

这个话题对于一些老鸟来说可能根本算不上疑问,但对于新手来说也许除了最常见的var之外,let和const较少使用的机会。

10740
来自专栏信安之路

利用Java反射和类加载机制绕过JSP后门检测

JSP 后门,一般是指文件名以 .jsp 等后缀结尾的,可运行于 Java servlet 及相关容器和组件内的通用 JSP 脚本。

37700
来自专栏纯洁的微笑

正则表达式和 CPU 100%有什么故事?

18120
来自专栏北京马哥教育

Python程序员最常犯的十个错误,看完你自己都笑了

本文由马哥教育Python自动化实战班4期学员推荐,转载自简书,作者为EarlGrey,内容略经小编改编和加工,观点跟作者无关,最后感谢作者的辛苦贡献与付出。 ...

29040
来自专栏微信公众号:Java团长

Java异常处理和设计

在程序设计中,进行异常处理是非常关键和重要的一部分。一个程序的异常处理框架的好坏直接影响到整个项目的代码质量以及后期维护成本和难度。试想一下,如果一个项目从头到...

15530
来自专栏Java帮帮-微信公众号-技术文章全总结

Java基础-day01-基础题

1. 简述java语言,具有哪些特性? (1).java语言是简单的 java语言是和c++语言类似的,其次java中丢弃了c++中一些难理解的特性,比如运算符...

29040
来自专栏C语言及其他语言

Python程序员最常犯的十个错误

来源:编程派 ? 不管是在学习还是工作过程中,人都会犯错。虽然Python的语法简单、灵活,但也一样存在一些不小的坑,一不小心,初学者和资深Python程序...

33670
来自专栏菩提树下的杨过

ruby学习笔记(11)--symbol与hash参数

symbol是啥就不深入的讨论了,只简单说说symbol的好处 ruby内部对于每个对象,都会有一个数字id用来标识并区分,可以用xxx.object_id来查...

191100

扫码关注云+社区

领取腾讯云代金券