如何读取没有换行符的文件?


374

在Python中,调用

temp = open(filename,'r').readlines()

产生一个列表,其中每个元素都是文件中的一行。这有点愚蠢,但是仍然:readlines()还向每个元素写入换行符,这是我不希望发生的事情。

我该如何避免呢?


4
使用地带:[l.strip('\n\r') for l in temp]。甚至rstrip。由于这里的迭代,它可以in open代替in temp
gorlum0 2012年

11
如果在Python 3中有一个值可以将open的newline参数设置为断断续续的尾随新行,那就太好了。
jxramos

Answers:


554

您可以使用读取整个文件并分割行str.splitlines

temp = file.read().splitlines()

或者,您可以手动删除换行符:

temp = [line[:-1] for line in file]

注意:仅当文件以换行符结尾时,后一种解决方案才有效,否则最后一行将丢失字符。

在大多数情况下,此假设是正确的(尤其是对于文本编辑器创建的文件,无论如何,它们通常都会添加结尾换行符)。

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

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]

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

[line.rstrip('\n') for line in file]

甚至,尽管很难理解:

[line[:-(line[-1] == '\n') or len(line)+1] for line in file]

这利用了以下事实:的返回值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

因为readline()保留换行符也readlines()保留它。

注意:为了readlines()使writelines()方法对称,不会添加结尾换行符,因此f2.writelines(f.readlines())会生成fin 的精确副本f2


1
请注意,这[line.rstrip('\n') for line in file]将删除多个尾随\n
Wes Turner

1
更简单地,[line[:-(line[-1] == '\n') or len(line)+1] for line in file]可以改为[line[:-(line[-1] == '\n') or None] for line in file]
Wes Turner

10
这些解决方案将整个文件读入内存。将列表理解的方括号更改为括号可生成一个生成器表达式,该表达式可让您一次遍历文件一行: for line in (x.strip() for x in f):
Joseph Sheedy

2
@velotron这不是问题/答案的重点。另外:请紧记,with关闭文件时,块终止,这意味着你不能这样做with open(...) as f: lines = (line for line in f)和使用lineswith,因为你会得到一个I / O错误。您可以使用genexp懒惰,但是在关闭文件之前必须先使用它。
巴库里

@WesTurner。但是尾随换行符不会超过一个。多余的换行符将成为下一个空行的一部分
Mad Physicist'Aug

38
temp = open(filename,'r').read().split('\n')

14
\r\n换行符会怎样?;)
Wolph 2012年

26
Python自动处理通用换行符,因此.split('\n')将独立于换行符约定正确地进行拆分。如果以二进制模式读取文件将很重要,在这种情况下可以splitlines()处理通用换行符而split('\n')不能。
Bakuriu 2012年

7
总是有os.linesep:)
askewchan

1
@LarsH,在某些情况下会有所帮助,在我的系统\r\n行末尾不会转换为\n,无论是读取为文本还是二进制,因此os.linesep在不行的地方\n都可以使用。但splitlines显然是更好的选择,在您提到文件与os不匹配的情况下。确实,我主要是在提及此讨论的情况下,以防人们不知道它的存在。
askewchan '16

1
@askewchan也许您正在使用Python的过时版本。我相信从Python 3开始,默认情况下\r\n会启用通用换行符,即即使您在Linux上运行,也将转换为文本文件。
亚瑟塔卡

13

另一个例子:

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

with open(filename, 'r') as fileobj:
    for row in fileobj:
        print( row.rstrip('\n') )

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

(python> = 2.0)


10
temp = open(filename,'r').read().splitlines()

5
您确定这会关闭文件吗?我认为并非如此,所以它实际上不是
单线的

9

我认为这是最好的选择。

temp = [line.strip() for line in file.readlines()]

8
此解决方案还删除了不必要的前导和尾随空格。
罗兰·伊利格

但是,这种理解真的很好。至少对于Python 3,可以使用它temp = [line.rstrip() for line in file.readlines()]来获取@Roland_Illig注释的目的。
bballdave025

如果要遍历所有行,为什么不那么懒惰?使用.readlines(),您可以有效地遍历整个文件两次。
AMC

1

尝试这个:

u=open("url.txt","r")  
url=u.read().replace('\n','')  
print(url)  

4
尽管此代码段可以解决问题,但提供说明确实有助于提高您的帖子质量。请记住,您将来会为读者回答这个问题,而这些人可能不知道您提出代码建议的原因。也请尽量不要在代码中添加解释性注释,因为这会降低代码和解释的可读性!
再见StackExchange

我不明白为什么有人应该在某些替代解决方案上使用它。
AMC

-1
my_file = open("first_file.txt", "r")
for line in my_file.readlines():
    if line[-1:] == "\n":
        print(line[:-1])
    else:
        print(line)
my_file.close() 

3
请添加一些说明,以便对其他人有用。
samuellawrentz

您应该使用上下文管理器来处理文件对象,并直接遍历文件。通过这样使用.readlines(),您可以有效地对整个文件进行两次迭代。
AMC

-2
import csv

with open(filename) as f:
    csvreader = csv.reader(f)
    for line in csvreader:
         print(line[0])

2
但是,如果行中有逗号怎么办?
镀金

-8
def getText():
    file=open("ex1.txt","r");

    names=file.read().split("\n");
    for x,word in enumerate(names):
        if(len(word)>=20):
            return 0;
            print "length of ",word,"is over 20"
            break;
        if(x==20):
            return 0;
            break;
    else:
        return names;


def show(names):
    for word in names:
        len_set=len(set(word))
        print word," ",len_set


for i in range(1):

    names=getText();
    if(names!=0):
        show(names);
    else:
        break;
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.