【问题标题】:Python decodes carriage return as line feedPython将回车解码为换行
【发布时间】:2019-03-15 14:36:49
【问题描述】:

我正在努力寻找解释为什么 python 将回车解码为换行符。

我这里有一个包含回车符 (\r) 的单行文本文件作为示例。 如果我将其作为指定编码的文本文件打开,则找不到与以二进制模式打开文件并使用相同编码对其进行解码时相同的字符串。

确实,当我以文本模式打开文件时,CR 字符被替换为换行符 (\n)。

为什么?

with open("text.txt", encoding="utf-8", mode="r") as f:
    txt = f.read()
txt
>>>'4312;"blabla";";\n";"blabla2"\n'

with open("text.txt", mode="rb") as f:
    txt2 = f.read()
txt2.decode("utf-8")
>>>'4312;"blabla";";\r";"blabla2"\n'

【问题讨论】:

    标签: python


    【解决方案1】:

    这与编码无关。

    当您以“r”(文本)模式打开文件时,将应用通用换行支持,除非您指定其他内容。其工作原理如下:

    从流中读取输入时,如果换行符为None,则通用 换行模式已启用。输入中的行可以以 '\n'、'\r' 或 '\r\n',这些在返回之前被翻译成'\n' 调用者。

    https://docs.python.org/3/library/io.htmlio.TextIOWrapper 类下。

    当您以“rb”(二进制)模式打开文件时,您会得到文件中的确切内容。

    您的文件中似乎包含\r,当您以文本模式阅读它时,您会将其规范化为\n。但是在二进制模式下,它(当然)没有被规范化,所以你会得到文件中实际存在的不一致的 EOL。

    【讨论】:

      【解决方案2】:

      这是因为open 函数的通用换行模式默认启用,会自动将'\r' 和'\r\n' 标准化为'\n'。如果您希望保留原始行结尾,则可以使用 newline='' 参数:

      with open("text.txt", encoding="utf-8", mode="r", newline='') as f:
      

      摘自documentation:

      newline 控制通用换行符的工作方式(它仅适用于文本 模式)。它可以是无、''、'\n'、'\r' 和 '\r\n'。它作为 如下:

      • 在输入时,如果newline 是None,则启用通用换行模式。输入中的行可以以'\n'、'\r' 或'\r\n' 结尾,这些是 在返回给调用者之前翻译成'\n'。如果是'', 通用换行模式已启用,但行尾返回 来电者未翻译。如果它具有任何其他合法价值, 输入行仅由给定的字符串终止,并且该行 结尾未翻译地返回给调用者。
      • 在输出时,如果newline 是None,则写入的任何'\n' 字符都将转换为系统默认行分隔符os.linesep。如果 换行符是'',不进行翻译。如果newline 是 其他合法值,写入的任何'\n' 字符都将转换为 给定字符串。

      【讨论】:

        【解决方案3】:

        open默认参数的完整列表是:

        open(file, mode='r', buffering=-1, encoding=None, errors=None, newline=None, closefd=True)
        

        newline=None 参数是您注意到的行为背后的原因。如果未指定此参数(也称为换行符=无),则会激活“通用换行符模式”。如文档中所述,here,这意味着\r\n 将自动转换为\n:

        在输入时,如果换行符为无,则启用通用换行符模式。 输入中的行可以以 '\n'、'\r' 或 '\r\n' 结尾,它们是 在返回给调用者之前翻译成'\n'。

        当您使用mode=rb 打开文件时,数据以字节形式加载,不会被解码,因此不会自动将\r 转换为\n。

        以二进制模式打开的文件(包括模式参数中的“b”) 将内容作为字节对象返回,无需任何解码


        PEP 278 -- Universal Newline Support 中有关通用换行支持的更多信息。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2014-12-11
          • 2023-04-10
          • 2012-09-05
          • 2016-10-23
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多