在r和rb模式下parsing文本文件的区别
在“r”模式下parsing文本文件比在“rb”模式下parsing文本文件更方便的是什么? 特别是当有问题的文本文件可能包含非ASCII字符。
这取决于你使用的是什么版本的Python。 在Python 2中, Chris Drappier的答案适用。
在Python 3中,它是一个不同的(也是更一致的)故事:在文本模式( 'r'
)中,Python将根据您提供的文本编码parsing文件(或者,如果您不提供,依赖的默认值),和read()
会给你一个str
。 在二进制( 'rb'
)模式下,Python不会假定文件中包含可合理parsing为字符的内容,而read()
则为您提供了一个bytes
对象。
此外,在Python 3中,通用换行符(在'\n'
和特定于平台的换行符之间转换,因此您不必关心它们)可用于任何平台上的文本模式文件,而不仅仅是Windows。
从文档 :
在Windows上,附加到模式的“b”以二进制模式打开文件,所以也有像“rb”,“wb”和“r + b”这样的模式。 Windows上的Python区分文本和二进制文件; 数据读取或写入时,文本文件中的行尾字符会自动稍微改变。 这种对文件数据的后台修改对于ASCII文本文件来说是很好的,但是它会破坏像JPEG或者EXE文件那样的二进制数据。 读取和写入这些文件时要非常小心地使用二进制模式。 在Unix上,在模式中附加一个'b'并不会造成什么影响,所以你可以在所有的二进制文件中使用它。
不同之处在于如何处理行尾(EOL)。 不同的操作系统使用不同的字符在Unix中标记EOL – \n
,在OS X之前的Mac版本中标记\r
,在Windows中标记\r\n
。 当以文本模式打开文件时,读取文件时,Python会用\n
replace从文件读取的操作系统特定的行尾字符。 反之亦然,也就是说,当您尝试将\n
写入以文本模式打开的文件时,它将写入操作系统特定的EOL字符。 你可以通过检查os.linesep
find你的操作系统默认的EOL。
当以二进制模式打开文件时,不会进行映射。 你读的是你得到的。 请记住,文本模式是默认模式。 所以,如果你正在处理非文本文件(图像,video等),请确保以二进制模式打开文件,否则最终会通过引入(或删除)一些字节来搞乱文件。
Python也有一个通用的换行模式。 当在这种模式下打开文件时,Python会将\r
, \n
和\r\n
所有字符映射到\n
。
为了澄清和回答阿戈斯蒂诺的评论/问题 (我没有足够的声誉来评论,所以我承认这是一个答案…):
在Python 2中,无论是文本模式还是二进制模式,都不会发生行结束修改,正如前面所述,在Python 2中, Chris Drappier的回答是适用的(请注意,其链接现在指向3.x Python文档,但是Chris引用的文本是当然是从Python 2的input输出教程 )
所以不, 在非Windows上用Python 2在文本模式下打开一个文件并不是真正的行结束修改:
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中以通用换行模式打开文件,该文件确实执行了所述行结束mod:
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'被转换为当前平台的默认行结束符除了在文本模式下字节解码/编码的字节< – >字节)之外。 例如,在Linux上读取一个Dos / Win CRLF行结束的文件将把行结束标准化为'\ n'。