我正在阅读一个文本文件:
f = open('data.txt')
data = f.read()
然而data
变量中的换行符被标准化为LF('\ n'),而文件包含CRLF('\ r \ n')。
如何指示Python按原样读取文件?
答案 0 :(得分:13)
在Python 2.x中:
f = open('data.txt', 'rb')
正如the docs所说:
默认设置是使用文本模式,它可以在写入时将“\ n”字符转换为特定于平台的表示,并在读取时返回。因此,在打开二进制文件时,您应该将
'b'
附加到模式值以在二进制模式下打开文件,这将提高可移植性。 (即使在不以不同方式处理二进制文件和文本文件的系统上,附加'b'
也很有用,它可用作文档。)
在Python 3.x中,有三种选择:
f1 = open('data.txt', 'rb')
这会使换行符保持未转换状态,但也会返回bytes
而不是str
,您必须自己明确decode
到Unicode。 (当然2.x版本还返回了必须手动解码的字节,如果你想要Unicode,但是2.x就是str
对象; 3.x str
是Unicode。 )
f2 = open('data.txt', 'r', newline='')
这将返回str
,并保留换行符。然而,与2.x等价物不同,readline
和朋友会将'\r\n'
视为换行符,而不是后续换行符的常规字符。通常这不重要,但如果确实如此,请记住它。
f3 = open('data.txt', 'rb', encoding=locale.getpreferredencoding(False))
这与2.x代码完全一样处理换行符,如果您刚刚使用了所有默认值,则使用相同的编码返回str
...但它在当前3中不再有效。 X
从流中读取输入时,如果换行为“无”,则启用通用换行模式。输入中的行可以以'\ n','\ r'或'\ r \ n'结尾,并且在返回给调用者之前将这些行转换为'\ n'。如果是'',则启用通用换行模式,但行结尾将返回给调用者未翻译。
您需要为f3
指定显式编码的原因是以二进制模式打开文件意味着默认从“使用locale.getpreferredencoding(False)
解码”更改为“不解码,并返回原始bytes
代替str
“。同样,来自the docs:
在文本模式下,如果未指定编码,则使用的编码与平台相关:调用locale.getpreferredencoding(False)以获取当前的语言环境编码。 (对于读取和写入原始字节,请使用二进制模式并保留编码未指定。)
然而:
'encoding'...只应在文本模式下使用。
至少从3.3开始,这是强制执行的;如果你尝试使用二进制模式,你会得到ValueError: binary mode doesn't take an encoding argument
。
所以,如果你想编写适用于2.x和3.x的代码,你会用什么?如果您想分别处理bytes
,显然f
和f1 are the same. But if you want to deal in
str , as appropriate for each version, the simplest answer is to write different code for each, probably
f and
f2`。如果这出现了很多,请考虑编写包装函数:
if sys.version_info >= (3, 0):
def crlf_open(path, mode):
return open(path, mode, newline='')
else:
def crlf_open(path, mode):
return open(path, mode+'b')
在编写多版本代码时要注意的另一件事是,如果你不编写可识别语言环境的代码,locale.getpreferredencoding(False)
几乎总是在3.x中返回合理的东西,但它通常会返回2.x. 'US-ASCII'
使用locale.getpreferredencoding(True)
在技术上是不正确的,但如果您不想考虑编码,可能更有可能是您真正想要的。 (尝试在2.x和3.x解释器中调用它以查看原因 - 或者阅读文档。)
当然,如果你真的知道文件的编码,那总是比猜测更好。
在任何一种情况下,'r'
表示“只读”。如果未指定模式,则默认值为'r'
,因此与默认值等效的二进制模式为'rb'
。
答案 1 :(得分:5)
您需要以二进制模式打开文件:
f = open('data.txt', 'rb')
data = f.read()
('r'
表示“读取”,'b'
表示“二进制”)
然后一切都按原样返回,没有任何标准化
答案 2 :(得分:4)
您可以使用codecs module来编写与版本无关的'代码:
底层编码文件始终以二进制模式打开。在读写时不会自动转换
'\n'
。 mode参数可以是内置open()
函数可接受的任何二进制模式; <{1}}会自动添加。
'b'
答案 3 :(得分:1)
只需在open
:
f = open('data.txt', 'rb')
data = f.read()
答案 4 :(得分:0)
使用open('data.txt', 'rb')
打开文件。请参阅doc。