文件——Unicode 文本文件

未匹配的标注

文本文件用来处理所有类型的基于文本的数据,从备忘录到电子邮件内容到JSON和XML文档。然而,在今天更广阔的互联世界,不问“什么类型?”就不能真正地谈论文本——如果文本的Unicode编码类型值和平台默认值不同,或因为数据可移植性原因而不能依赖于该默认值,则还需要知道该类型值。

幸运的是,这比听起来的要容易。要访问本章开头介绍的那种包括非ASCII Unicode 文本的文件,如果文件中文本和平台的默认编码不匹配,则可以简单地传入一个编码名称。在此模式下,Python文本文件根据提供的编码方案名称,自动对写入编码和对读取解码。在 Python 3系列

>>> S = 'sp\xc4m' # 非 ASCII Unicode 文本
>>> S
'spÄm'
>>> S[2] # 字符序列
'Ä'
>>> file = open('unidata.txt', 'w', encoding='utf-8') # 写入/编码 UTF-8 文本
>>> file.write(S) # 写入4个字符
4
>>> file.close()
>>> text = open('unidata.txt', encoding='utf-8').read() # 读取/解码 UTF-8 文本
>>> text
'spÄm'
>>> len(text) # 4个字符(码点)
4

这种自动的编码和解码通常是你想要的。因为文件在传入中进行这个处理,可能在内存中将文本作为一个简单的字符串来处理,而无需要考虑它的Unicode编码源。然而,如果需要的话,还可以通过使用二进制模式来查看存在文件中的真实内容:

>>> raw = open('unidata.txt', 'rb').read() # 读取原始的编码字节
>>> raw
b'sp\xc3\x84m'
>>> len(raw) # 在UTF-8中其实有5个字节
5

如果从一个非文件的源获取Unicode 数据(比如,解析一条电子邮件信息或从网络连接获取信息),还可以手动编码和解码:

>>> text.encode('utf-8') # 手动编码为字节
b'sp\xc3\x84m'
>>> raw.decode('utf-8') # 手动解码为字符串
'spÄm'

这对了解文本文件在不同编码名称下如何自动地编码同样的字符串也是有用的,而且还提供了翻译数据为不同编码的方法——在文件中是不同的字节,但如果提供了合适的编码名称,会在内存中解码为同一个字符串。

>>> text.encode('latin-1') # 在其他编码中字节是不同的
b'sp\xc4m'
>>> text.encode('utf-16')
b'\xff\xfes\x00p\x00\xc4\x00m\x00'
>>> len(text.encode('latin-1')), len(text.encode('utf-16'))
(4, 10)
>>> b'\xff\xfes\x00p\x00\xc4\x00m\x00'.decode('utf-16') # 但解码的是同一个字符串
'spÄm'

Python 2系列 中这些都差不多,但Unicode字符串被编码而且显示带有前导“u”,字节字符串不需要或显示前导“b”,且Unicode 文本文件必须用 codecs.open (它就像 3系列的 open接收一个编码名称,且使用特殊的 unicode 字符串来表示内存中的内容)来打开。在2系列中,二进制文件模式可能看起来可选,因为普通文件只是基于字节的数据,但如果存在该模式,就必须避免改变行末尾符(EOL)(更多参阅本书后面):

>>> import codecs
>>> codecs.open('unidata.txt', encoding='utf8').read() # 2系列:读取/解码 文本
u'sp\xc4m'
>>> open('unidata.txt', 'rb').read() # 2系列:读取原始字节
'sp\xc3\x84m'
>>> open('unidata.txt').read() # 2系列:同样是原始/未解码
'sp\xc3\x84m'

如果只处理 ASCII 文本,通常不需要考虑这个不同,但如果处理二进制数据(包括大多数媒体类型)或国际化字符集(包括当今Web和Internet上大部分内容)中的文本,则Python的字符串和文件是一个优势。Python还支持非ASCII文件名称(不只是内容),但很大程度上是自动的;当需要时,像 walkers 和 listers 这些工具提供了更多控制,然而进一步的细节将推迟到 第37章

本文章首发在 LearnKu.com 网站上。

上一篇 下一篇
讨论数量: 0
发起讨论 只看当前版本


暂无话题~