繁体   English   中英

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

[英]Don't convert newline when reading a file

我正在读一个文本文件:

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

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

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

在Python 2.x中:

f = open('data.txt', 'rb')

正如文档所说:

默认设置是使用文本模式,可以在写入时将“\\ 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 ”。 再次,从文档

在文本模式下,如果未指定编码,则使用的编码与平台相关:调用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 are the same. But if you want to deal in , as appropriate for each version, the simplest answer is to write different code for each, probably 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)语言环境的代码, locale.getpreferredencoding(False)几乎总是在3.x中返回合理的东西,但它通常会返回'US-ASCII'在2.x. 使用locale.getpreferredencoding(True)在技​​术上是不正确的,但如果您不想考虑编码,可能更有可能是您真正想要的。 (尝试在2.x和3.x解释器中调用它以查看原因 - 或者阅读文档。)

当然,如果你真的知道文件的编码,那总是比猜测更好。

在任何一种情况下, 'r'表示“只读”。 如果未指定模式,则默认为'r' ,因此等效于默认值的二进制模式为'rb'

您需要以二进制模式打开文件:

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

'r'代表“读”, 'b'代表“二进制”)

然后一切都按原样返回,没有任何标准化

您可以使用编解码器模块编写“版本无关”代码:

底层编码文件始终以二进制模式打开。 在读写时不会自动转换'\\n' mode参数可以是内置open()函数可接受的任何二进制模式; 'b'会自动添加。

import codecs
with codecs.open('foo', mode='r', encoding='utf8') as f:
    # python2: u'foo\r\n'
    # python3: 'foo\r\n'
    f.readline()

只需在open请求“读取二进制”:

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

使用open('data.txt', 'rb')打开文件。 文档

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM