使用.readlines()时如何去除换行符\n

394
我有一个包含数值的 .txt 文件。
数值以以下方式列出:
Value1
Value2
Value3
Value4

我的目标是将这些值放入一个列表中。当我这样做时,列表看起来像这样:['Value1\n','Value2\n',...]。不需要\n。以下是我的代码:
t = open('filename.txt')
contents = t.readlines()

3
通常情况下,你不希望先读取所有行并将其存储在缓冲区中,然后再去除换行符/splitlines(),因为如果文件很大,这种做法会浪费2倍的内存。相反,你需要在读取每一行时通过 rstrip() 方法去除该行的换行符并进行迭代。 - smci
11个回答

546

这应该会做你想要的事情(将文件内容按行以列表形式呈现,去除 \n)

with open(filename) as f:
    mylist = f.read().splitlines() 

2
mylist = [i for i in mylist if i != ''] - TheRutubeify
7
@bfrederix提供的URL已经失效。这里提供一个archive.org的备份链接: https://web.archive.org/web/20160215030807/http://axialcorps.com/2013/09/27/dont-slurp-how-to-read-files-in-python/ - Paolo Melchiorre
2
最适合小文件的解决方案。 - Anselmo Blanco Dominguez

156
我会这样做:
alist = [line.rstrip() for line in open('filename.txt')]

或者:

with open('filename.txt') as f:
    alist = [line.rstrip() for line in f]

34
这可能会除去不止 \n - gronostaj
24
根据我的经验,行末空格(空格、制表符、回车、换行等)通常都是不必要的。在我过去二十多年处理的各种数据和计算机语言中,从未需要行末空格。因此,它会被剥离掉不止\n(指换行符)。很可能你不会想念它。 - hughdbrown
5
一种可能会有影响的情况是对一个用制表符分隔的文件进行去除右侧空白操作,如果某些行在最右侧有多个空值,则这些行会比其他行长度更短,如果按照 \t 进行拆分的话... - duhaime
4
你有点改变了话题。如果有人问:“我该如何读取一个以CR分隔行,其中包含以Tab分隔字段的文件?”,我一定会建议使用Python的CSV模块。我不会给出适用于纯文本文件的CR分隔数据行的提示。因此,如果是以tab分隔的值,那么这样做是不好的,如果这样陈述,我的建议永远不会是这样的。 - hughdbrown
4
@hughdbrown 阿门,我只是想将其标记为 gronostaj 的评论的一个潜在例子,因为这是使用 readlines 去除 \n 的第一个 Google 搜索结果。尽管如此,我理解您的观点! - duhaime
显示剩余2条评论

144
你可以使用 .rstrip('\n') 来仅删除字符串末尾的换行符:

for i in contents:
    alist.append(i.rstrip('\n'))

这将保留所有其他空格不变。如果您不关心行首和行尾的空格,则可以使用.strip()重型工具。

然而,由于您正在从文件中读取并将所有内容都加载到内存中,最好使用str.splitlines()方法;这个方法会在行分隔符上拆分一个字符串,并返回一个没有这些分隔符的行列表;将其用于file.read()结果,完全不要使用file.readlines()

alist = t.read().splitlines()

11
file.read().splitlines() 能够完美地完成工作,但是我需要每次访问这个页面只是为了提醒自己如何做。天啊,我希望他们能像 file.readlines(newlines=False) 一样以一种直观的方式包含这个功能。 - pcko1
6
我觉得这并不更加直观。无论如何我总是将文件对象用作可迭代对象(因此会使用list(file)而不是file.readlines()),因此知道要期望换行符。主要是尝试将文件中的每一行视为一个流,并进行迭代处理。使用for line in file: dosomething(line)[dosomething(line) for line in file],而不是将所有行读入内存。 - Martijn Pieters

27
在打开文件后,列表推导可以在一行中完成此操作:
fh=open('filename')
newlist = [line.rstrip() for line in fh.readlines()]
fh.close()

记得在之后关闭你的文件。


9
记得在使用后关闭文件。要么使用上下文管理器以避免风险。 - AMC
不需要使用readlines。文件本身就是一个迭代器,所以你可以循环它。 - Manny Fleurmond

16
我使用strip函数去除换行符,因为对4GB的文件进行split操作会导致内存错误。
示例代码:
with open('C:\\aapl.csv','r') as apple:
    for apps in apple.readlines():
        print(apps.strip())

3
如果你这样使用.readlines(),实际上你会两次遍历整个文件,并且同时一次性将整个文件保存在内存中。 - AMC

15
对于列表中的每个字符串,使用.strip(),它可以从字符串开头或结尾删除空格:
for i in contents:
    alist.append(i.strip())

但是根据您的使用情况,如果您需要从文件中读取数据并获得漂亮的数组,则最好使用类似于numpy.loadtxt或者numpy.genfromtxt的东西。


11
from string import rstrip

with open('bvc.txt') as f:
    alist = map(rstrip, f)

注意: rstrip()会移除空格,也就是说:\f\n\r\t\v\x和空白字符都会被移除,但我想你只对保留行中的有效字符感兴趣。那么,仅使用map(strip, f)更合适,同时还会删除前导空格。
如果你真的只想消除 NL (\n) 和 RF (\r) 符号,可以这样做:
with open('bvc.txt') as f:
    alist = f.read().splitlines()

如果不传递参数,splitlines()函数将不保留NL和RF符号(至少在我的机器上,Windows记录文件时会在行末添加NLRF),但会保留其他空格,特别是空格和制表符。

.

with open('bvc.txt') as f:
    alist = f.read().splitlines(True)

具有相同的效果,就像

with open('bvc.txt') as f:
    alist = f.readlines()

也就是说,NL和RF被保留。

6

我遇到了同样的问题,我发现以下解决方案非常有效。希望它能帮助你或其他想要做同样事情的人。

首先,我会使用“with”语句,因为它可以确保文件的正确打开和关闭。

代码应该类似于:

with open("filename.txt", "r+") as f:
    contents = [x.strip() for x in f.readlines()]

如果您想将这些字符串(内容列表中的每个项目都是字符串)转换为整数或浮点数,可以执行以下操作:

contents = [float(contents[i]) for i in range(len(contents))]

如果你想转换为整数,请使用int而不是float

这是我在SO上的第一个答案,如果格式不正确请见谅。


4
我猜 f.read().splitlines() 会更有效率。如果需要将数字转换为整数或浮点数,则 map(int, f.read().splitlines()) 可能更好。 - thiruvenkadam
通过像这样使用.readlines(),您实际上是在整个文件上进行两次迭代,同时一次性将整个文件保留在内存中。 - AMC

2

最近我使用了以下方法来读取文件中的所有行:

alist = open('maze.txt').read().split()

或者您可以使用这个来增加一点额外的安全性:
with f as open('maze.txt'):
    alist = f.read().split()

在单行文本中间有空格时,它无法工作,但是您的示例文件似乎没有使用空格分隔值。这是一个简单的解决方案,它返回准确的值列表,并且不会为每个空行(例如文件末尾的换行符)添加空字符串''

使用这个解决方案有什么好处吗?你只是避免了输入五个字符而已吗? - AMC

-1
with open('D:\\file.txt', 'r') as f1:
    lines = f1.readlines()
lines = [s[:-1] for s in lines]

3
通过这样使用 .readlines(),你实际上是在整个文件上进行两次迭代,同时一次性将整个文件存储在内存中。不仅如此,还要注意,使用 s[:-1] 可能会移除文件的最后一个非换行符字符。我认为与其他解决方案相比,没有任何好处。 - AMC

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接