读取没有换行符的文件

Yot*_*tam 320 python line-breaks readlines

在Python中,调用

temp = open(filename,'r').readlines()
Run Code Online (Sandbox Code Playgroud)

得到一个列表,其中每个元素都是文件中的一行.它有点愚蠢但仍然:readlines()还为每个元素写了换行符,这是我不希望发生的.我怎么能避免呢?

Bak*_*riu 478

您可以使用以下方法读取整个文件和拆分行str.splitlines:

temp = file.read().splitlines()
Run Code Online (Sandbox Code Playgroud)

或者您可以手动剥离换行符:

temp = [line[:-1] for line in file]
Run Code Online (Sandbox Code Playgroud)

注意:最后一个解决方案仅在文件以换行符结束时才有效,否则最后一行将丢失一个字符.

在大多数情况下,这种假设是正确的(特别是对于由文本编辑器创建的文件,它们通常添加结束换行符).

如果您想避免这种情况,可以在文件末尾添加换行符:

with open(the_file, 'r+') as f:
    f.seek(-1, 2)  # go at the end of the file
    if f.read(1) != '\n':
        # add missing newline if not already present
        f.write('\n')
        f.flush()
        f.seek(0)
    lines = [line[:-1] for line in f]
Run Code Online (Sandbox Code Playgroud)

或者更简单的替代方法是strip换行:

[line.rstrip('\n') for line in file]
Run Code Online (Sandbox Code Playgroud)

甚至,虽然很不可读:

[line[:-(line[-1] == '\n') or len(line)+1] for line in file]
Run Code Online (Sandbox Code Playgroud)

这利用了返回值or不是布尔值,但被评估为true或false的对象的事实.


readlines方法实际上相当于:

def readlines(self):
    lines = []
    for line in iter(self.readline, ''):
        lines.append(line)
    return lines

# or equivalently

def readlines(self):
    lines = []
    while True:
        line = self.readline()
        if not line:
            break
        lines.append(line)
    return lines
Run Code Online (Sandbox Code Playgroud)

因为readline()保持新线也readlines()保持它.

注:为对称性readlines()writelines()方法并没有添加新行结束,因此f2.writelines(f.readlines())产生的精确副本ff2.

  • 这些解决方案将整个文件读入内存.将列表推导的方括号更改为括号会生成一个生成器表达式,它允许您一次迭代一行文件:`for line in(x.strip()for f in f): (7认同)
  • @velotron 这不是问题/答案的真正重点。另外:请记住,当块终止时,`with` 会关闭文件,这意味着你不能使用 `with open(...) as f:lines = (line for line in f)` 并在外部使用 `lines` `with` 因为你会得到一个 I/O 错误。您可以使用 genexp 来偷懒,但您必须在关闭文件之前使用它。 (3认同)
  • 请注意``[line.rstrip('\n') for line in file]`` 将删除多个尾随``\n``。 (2认同)
  • @韦斯特纳。但尾随换行符不会超过一个。额外的换行符将成为下一个空行的一部分 (2认同)

viv*_*vek 30

temp = open(filename,'r').read().split('\n')
Run Code Online (Sandbox Code Playgroud)

  • Python自动处理通用换行符,因此`.split('\n')`将正确分割,与换行符约定无关.如果你以二进制模式读取文件会很重要.在这种情况下,`splitlines()`处理通用换行符,而split('\n')`则不处理. (22认同)
  • 但是`\ r \n`换行符会发生什么?;) (12认同)
  • 而且总有`os.linesep` :) (7认同)
  • `open()` [默认为读取模式](https://docs.python.org/3/library/functions.html#open)。您不必传递“r”。 (5认同)

Dav*_*son 12

我最喜欢的一句台词——如果你不算的话from pathlib import Path:)

lines = Path(filename).read_text().splitlines()
Run Code Online (Sandbox Code Playgroud)

它会自动关闭文件,无需with open()...

Python 3.5 中添加。

https://docs.python.org/3/library/pathlib.html#pathlib.Path.read_text


O95*_*O95 11

另一个例子:

一次读取文件。从字符串结尾删除不需要的字符str.rstrip(chars)

with open(filename, 'r') as fileobj:
    for row in fileobj:
        print( row.rstrip('\n') )
Run Code Online (Sandbox Code Playgroud)

又见str.strip([chars])str.lstrip([chars])

(python> = 2.0)


Mar*_*cel 9

temp = open(filename,'r').read().splitlines()
Run Code Online (Sandbox Code Playgroud)

  • 您确定这会关闭文件吗?我认为并非如此,因此它实际上不是单线的。 (3认同)

小智 9

我认为这是最好的选择。

temp = [line.strip() for line in file.readlines()]
Run Code Online (Sandbox Code Playgroud)

  • 此解决方案还删除了不必要的前导和尾随空格。 (4认同)
  • 需要明确的是,“readlines()”调用是多余的,因此这可能只是“temp = [line.strip() for line in file]”。 (4认同)