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

the*_*eta 3 python

我正在读一个文本文件:

f = open('data.txt')
data = f.read()
Run Code Online (Sandbox Code Playgroud)

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

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

aba*_*ert 13

在Python 2.x中:

f = open('data.txt', 'rb')
Run Code Online (Sandbox Code Playgroud)

正如文档所说:

默认设置是使用文本模式,可以在写入时将"\n"字符转换为特定于平台的表示,并在读取时返回.因此,在打开二进制文件时,您应该附加'b'模式值以二进制模式打开文件,这将提高可移植性.('b'即使在不以不同方式处理二进制文件和文本文件的系统上,附加也很有用,它用作文档.)

在Python 3.x中,有三种选择:

f1 = open('data.txt', 'rb')
Run Code Online (Sandbox Code Playgroud)

这将使换行符保持未转换状态,但也会返回bytes而不是str,您必须自己明确地decode使用Unicode.(当然2.x版本还返回了必须手动解码的字节,如果你想要Unicode,但是2.x就是一个str对象; 3.x str是Unicode.)

f2 = open('data.txt', 'r', newline='')
Run Code Online (Sandbox Code Playgroud)

这将返回str,并保留换行符.然而,readline与2.x等价物不同,朋友会将其'\r\n'视为换行符,而不是常规字符,后跟换行符.通常这没关系,但如果确实如此,请记住.

f3 = open('data.txt', 'rb', encoding=locale.getpreferredencoding(False))
Run Code Online (Sandbox Code Playgroud)

这与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 instr , as appropriate for each version, the simplest answer is to write different code for each, probablyf andf2`.如果这出现了很多,请考虑编写包装函数:

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')
Run Code Online (Sandbox Code Playgroud)

在编写多版本代码时要注意的另一件事是,如果你不编写可识别语言环境的代码,locale.getpreferredencoding(False)几乎总是在3.x中返回合理的东西,但它通常只返回'US-ASCII'2.x. 使用locale.getpreferredencoding(True)在技​​术上是不正确的,但如果你不想考虑编码,可能更有可能是你真正想要的.(尝试在2.x和3.x解释器中调用它以查看原因 - 或者阅读文档.)

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

在任何一种情况下,均为'r'"只读".如果未指定模式,则默认为'r',因此二进制模式等效于默认值'rb'.


ber*_*eal 5

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

f = open('data.txt', 'rb')
data = f.read()
Run Code Online (Sandbox Code Playgroud)

('r'用于"读取",'b'用于"二进制")

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