阅读文件时不要转换换行符

时间:2013-01-07 19:09:33

标签: python

我正在阅读一个文本文件:

f = open('data.txt')
data = f.read()

然而data变量中的换行符被标准化为LF('\ n'),而文件包含CRLF('\ r \ n')。

如何指示Python按原样读取文件?

5 个答案:

答案 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