在r和rb模式下解析文本文件之间的区别

时间:2012-03-10 05:13:06

标签: python file-io text-parsing

使用'r'模式解析文本文件比在'rb'模式下解析更方便的原因是什么? 特别是当有问题的文本文件可能包含非ASCII字符时。

4 个答案:

答案 0 :(得分:59)

这取决于你正在使用的Python版本。在Python 2中,Chris Drappier's answer适用。

在Python 3中,它是一个不同的(更一致的)故事:在文本模式('r')中,Python将根据您提供的文本编码解析文件(或者,如果您不提供一,平台相关的默认值),read()将为您提供str。在二进制('rb')模式下,Python不假定文件包含可以合理地解析为字符的内容,而read()会为您提供bytes对象。

此外,在Python 3中,通用换行符('\n'和特定于平台的换行符约定之间的转换,因此您不必关心它们)可用于上的文本模式文件平台,而不仅仅是Windows。

答案 1 :(得分:22)

来自documentation

  

在Windows上,附加到模式的'b'以二进制模式打开文件,因此还有'rb','wb'和'r + b'等模式。 Windows上的Python区分了文本和二进制文件;读取或写入数据时,文本文件中的行尾字符会自动稍微改变。这种对文件数据的幕后修改适用于ASCII文本文件,但它会破坏像JPEG或EXE文件中的二进制数据。在读取和写入此类文件时要非常小心地使用二进制模式。在Unix上,将'b'附加到该模式并没有什么坏处,因此您可以将它独立于平台用于所有二进制文件。

答案 2 :(得分:12)

区别在于如何处理行尾(EOL)。不同的操作系统使用不同的字符来标记EOL - 在Unix中为\n,在OS X之前的Mac版本中为\r,在Windows中为\r\n。在文本模式下打开文件时,读取文件时,Python将仅使用\n替换从文件中读取的特定于操作系统的行尾字符。反之亦然,即当您尝试将\n写入以文本模式打开的文件时,它将编写特定于操作系统的EOL字符。您可以通过选中os.linesep找到您的操作系统默认EOL。

以二进制模式打开文件时,不会进行映射。你读的是你得到的。请记住,文本模式是默认模式。因此,如果您正在处理非文本文件(图像,视频等),请确保以二进制模式打开文件,否则您最终会通过引入(或删除)某些字节来搞乱文件。

Python也有一个通用换行模式。在此模式下打开文件时,Python会将所有字符\r\n\r\n映射到\n

答案 3 :(得分:2)

澄清并回答Agostino's comment/question(我没有足够的声誉发表评论,所以请耐心等待我的回答......):

在Python 2中,没有行结束修改,无论是文本还是二进制模式 - 如前所述,在Python 2中Chris Drappier's answer适用(请注意,它现在的链接指向3.x Python文档,但Chris引用的文字当然来自Python 2 input and output tutorial

所以不,在非Windows 上使用Python 2 text 模式下打开文件是否会进行任何行结束修改:

0 $ cat data.txt 
line1
line2
line3
0 $ file data.txt 
data.txt: ASCII text, with CRLF line terminators
0 $ python2.7 -c 'f = open("data.txt"); print f.readlines()'
['line1\r\n', 'line2\r\n', 'line3\r\n']
0 $ python2.7 -c 'f = open("data.txt", "r"); print f.readlines()'
['line1\r\n', 'line2\r\n', 'line3\r\n']
0 $ python2.7 -c 'f = open("data.txt", "rb"); print f.readlines()'

然而,可以在Python 2中以通用换行模式打开文件,它完全执行所述行结束模式:

0 $ python2.7 -c 'f = open("data.txt", "rU"); print f.readlines()'
['line1\n', 'line2\n', 'line3\n']

(从Python 3.x开始,不推荐使用通用换行模式说明符)

另一方面,在Python 3上,在文本模式下读取文件时,特定于平台的行结束会被标准化为“\ n”,而在写入时,“\ n”会转换为当前平台的默认行结束文本模式(除了文本模式中的字节< - > unicode< - >字节解码/编码)之外。例如。在Linux上读取Dos / Win CRLF行结束文件会将行结束规范化为'\ n'。