如何从文件中读取特定的行(按行号)?

我正在使用for循环来读取文件,但我只想读取特定的行,例如行#26#30。是否有任何内置功能来实现这一点?

738374 次浏览

文件对象有一个.readlines()方法,它将为您提供文件内容的列表,每个列表项一行。在此之后,您可以使用普通的列表切片技术。

http://docs.python.org/library/stdtypes.html#file.readlines

这个怎么样:

>>> with open('a', 'r') as fin: lines = fin.readlines()
>>> for i, line in enumerate(lines):
if i > 30: break
if i == 26: dox()
if i == 30: doy()

简单的回答是:

f=open('filename')
lines=f.readlines()
print lines[25]
print lines[29]

或者:

lines=[25, 29]
i=0
f=open('filename')
for line in f:
if i in lines:
print i
i+=1

有一个更优雅的解决方案来提取许多行:linecache(由如何跳转到一个巨大文本文件中的特定行?提供,之前的stackoverflow.com问题)。

引用上面链接的python文档:

>>> import linecache
>>> linecache.getline('/etc/passwd', 4)
'sys:x:3:3:sys:/dev:/bin/sh\n'

4更改为您想要的行号,然后启动。注意,4将带来第五行,因为计数是从零开始的。

如果文件可能非常大,并且在读入内存时引起问题,那么使用@Alok的建议和使用enumerate()可能是一个好主意。

结论:

  • 使用fileobject.readlines()for line in fileobject作为小文件的快速解决方案。
  • 使用linecache作为一个更优雅的解决方案,它将非常快地读取许多文件,可能是重复的。
  • @Alok的建议,使用enumerate()用于可能非常大且无法装入内存的文件。注意,使用此方法可能会变慢,因为文件是按顺序读取的。

如果你不介意导入,那么fileinput正好可以满足你的需要(这是你可以读取当前行的行号)

如果要读取的文件很大,并且你不想一次在内存中读取整个文件:

fp = open("file")
for i, line in enumerate(fp):
if i == 25:
# 26th line
elif i == 29:
# 30th line
elif i > 29:
break
fp.close()

注意,i == n-1用于__abc1行。


在Python 2.6或更高版本中:

with open("file") as fp:
for i, line in enumerate(fp):
if i == 25:
# 26th line
elif i == 29:
# 30th line
elif i > 29:
break

您可以执行寻求()调用,将读头定位到文件中的指定字节。这对您没有帮助,除非您确切地知道在要读取的行之前文件中写入了多少字节(字符)。也许你的文件是严格格式化的(每一行是X个字节?)或者,如果你真的想提高速度,你可以自己计算字符的数量(记得包括不可见的字符,比如换行符)。

否则,您必须在您想要的行之前阅读每一行,就像这里已经提出的许多解决方案之一一样。

def getitems(iterable, items):
items = list(items) # get a list from any iterable and make our own copy
# since we modify it
if items:
items.sort()
for n, v in enumerate(iterable):
if n == items[0]:
yield v
items.pop(0)
if not items:
break


print list(getitems(open("/usr/share/dict/words"), [25, 29]))
# ['Abelson\n', 'Abernathy\n']
# note that index 25 is the 26th item
f = open(filename, 'r')
totalLines = len(f.readlines())
f.close()
f = open(filename, 'r')


lineno = 1
while lineno < totalLines:
line = f.readline()


if lineno == 26:
doLine26Commmand(line)


elif lineno == 30:
doLine30Commmand(line)


lineno += 1
f.close()

我更喜欢这种方法,因为它更通用,即你可以在文件上使用它,在f.readlines()的结果上,在StringIO对象上,无论什么:

def read_specific_lines(file, lines_to_read):
"""file is any iterable; lines_to_read is an iterable containing int values"""
lines = set(lines_to_read)
last = max(lines)
for n, line in enumerate(file):
if n + 1 in lines:
yield line
if n + 1 > last:
return


>>> with open(r'c:\temp\words.txt') as f:
[s for s in read_specific_lines(f, [1, 2, 3, 1000])]
['A\n', 'a\n', 'aa\n', 'accordant\n']

一个快速而紧凑的方法可以是:

def picklines(thefile, whatlines):
return [x for i, x in enumerate(thefile) if i in whatlines]

它接受任何打开的类文件对象thefile(由调用者决定是否应该从磁盘文件打开,还是通过例如套接字或其他类文件流打开)和一组从零开始的行索引whatlines,并返回一个具有低内存占用和合理速度的列表。如果要返回的行数非常多,你可能更喜欢使用生成器:

def yieldlines(thefile, whatlines):
return (x for i, x in enumerate(thefile) if i in whatlines)

这基本上只适用于循环——注意,唯一的区别是在return语句中使用圆括号而不是方括号,分别生成一个列表推导式和一个生成器表达式。

进一步注意,尽管提到了“lines”和“file”,但这些函数更通用——它们将在任何可迭代对象上工作,无论是打开的文件还是其他任何文件,根据逐级递增的项号返回项的列表(或生成器)。所以,我建议使用更合适的通用名称;-)。

@OP,你可以使用枚举

for n,line in enumerate(open("file")):
if n+1 in [26,30]: # or n in [25,29]
print line.rstrip()

这是我的2美分,不管它是否值得;)

def indexLines(filename, lines=[2,4,6,8,10,12,3,5,7,1]):
fp   = open(filename, "r")
src  = fp.readlines()
data = [(index, line) for index, line in enumerate(src) if index in lines]
fp.close()
return data




# Usage below
filename = "C:\\Your\\Path\\And\\Filename.txt"
for line in indexLines(filename): # using default list, specify your own list of lines otherwise
print "Line: %s\nData: %s\n" % (line[0], line[1])

如果你想看第7行

line = open("file.txt", "r").readlines()[7]

为了提供另一种解决方案:

import linecache
linecache.getline('Sample.txt', Number_of_Line)

我希望这是快速和简单的:)

为了完整起见,这里还有一个选项。

让我们从python文档中的定义开始:

通常包含一个序列的一部分的对象。slice使用下标符号[]创建,当给出几个数字时,数字之间使用冒号,例如variable_name[1:3:5]。括号(下标)表示法在内部使用切片对象(或在旧版本中使用__getslice__()和__setslice__())。

虽然片表示法一般不直接适用于迭代器,但itertools包包含一个替换函数:

from itertools import islice


# print the 100th line
with open('the_file') as lines:
for line in islice(lines, 99, 100):
print line


# print each third line until 100
with open('the_file') as lines:
for line in islice(lines, 0, 100, 3):
print line

该函数的另一个优点是,它直到结束才读取迭代器。所以你可以做更复杂的事情:

with open('the_file') as lines:
# print the first 100 lines
for line in islice(lines, 100):
print line


# then skip the next 5
for line in islice(lines, 5):
pass


# print the rest
for line in lines:
print line

为了回答最初的问题:

# how to read lines #26 and #30
In [365]: list(islice(xrange(1,100), 25, 30, 4))
Out[365]: [26, 30]

读取文件非常快。读取一个100MB的文件需要不到0.1秒(参见我的文章使用Python读写文件)。因此,你应该完整地阅读它,然后处理单行。

大多数回答这里做的不是错,而是风格不好。打开文件应该总是用with来完成,因为它可以确保文件再次关闭。

所以你应该这样做:

with open("path/to/file.txt") as f:
lines = f.readlines()
print(lines[26])  # or whatever you want to do with this line
print(lines[30])  # or whatever you want to do with this line

巨大的文件

如果你有一个巨大的文件,内存消耗是一个问题,你可以逐行处理它:

with open("path/to/file.txt") as f:
for i, line in enumerate(f):
pass  # process line i

我认为这行得通

 open_file1 = open("E:\\test.txt",'r')
read_it1 = open_file1.read()
myline1 = []
for line1 in read_it1.splitlines():
myline1.append(line1)
print myline1[0]
file = '/path/to/file_to_be_read.txt'
with open(file) as f:
print f.readlines()[26]
print f.readlines()[30]

使用with语句打开文件,打印第26行和第30行,然后关闭文件。简单!

对于阿洛克·辛格尔的回答,这是一个更好的小变化

fp = open("file")
for i, line in enumerate(fp,1):
if i == 26:
# 26th line
elif i == 30:
# 30th line
elif i > 30:
break
fp.close()

你可以用已经有人提到过的语法很简单地做到这一点,但这是迄今为止最简单的方法:

inputFile = open("lineNumbers.txt", "r")
lines = inputFile.readlines()
print (lines[0])
print (lines[2])

其中一些很可爱,但可以做得更简单:

start = 0 # some starting index
end = 5000 # some ending index
filename = 'test.txt' # some file we want to use


with open(filename) as fh:
data = fin.readlines()[start:end]


print(data)

这将使用简单的列表切片,它加载整个文件,但大多数系统将适当地最小化内存使用,它比上面给出的大多数方法都快,并且适用于我的10G+数据文件。好运!

打印所需的行。

.

.
def dline(file,no,add_sub=0):
tf=open(file)
for sno,line in enumerate(tf):
if sno==no-1+add_sub:
print(line)
tf.close()

执行---->dline("D:\dummy.txt",6)即dline("文件路径",line_number,如果你想要搜索行的上行给出1为低-1这是可选的默认值将采取0)

打印第3行,

line_number = 3


with open(filename,"r") as file:
current_line = 1
for line in file:
if current_line == line_number:
print(file.readline())
break
current_line += 1

原作者:Frank Hofmann

如果你的大型文本文件file是严格结构良好的(意味着每一行都有相同的长度l),你可以使用n-th行

with open(file) as f:
f.seek(n*l)
line = f.readline()
last_pos = f.tell()

免责声明这只适用于具有相同长度的文件!

相当快,切中要害。

打印文本文件中的某些行。创建一个“lines2print”列表然后 当枚举“在”lines2print列表中时,只需打印。 要去除多余的'\n',请使用line.strip()或line.strip('\n')。 我只是喜欢“列表理解”,并尽可能地使用它。 我喜欢用“with”方法来读取文本文件,以防止

.打开文件
lines2print = [26,30] # can be a big list and order doesn't matter.


with open("filepath", 'r') as fp:
[print(x.strip()) for ei,x in enumerate(fp) if ei in lines2print]

或者如果list很小,只需在理解式中输入list作为列表。

with open("filepath", 'r') as fp:
[print(x.strip()) for ei,x in enumerate(fp) if ei in [26,30]]
如果你想读取特定的行,比如从某个阈值行开始的行,那么你可以使用以下代码, file = open("files.txt","r") Lines = file.readlines() ##转换为行列表 data = lines[11:] ## raed特定的行

从某一行读出:

n = 4   # for reading from 5th line
with open("write.txt",'r') as t:
for i,line in enumerate(t):
if i >= n:             # i == n-1 for nth line
print(line)
with open("test.txt", "r") as fp:
lines = fp.readlines()
print(lines[3])

test.txt是文件名
.txt 打印test.txt

中的第4行

不要使用readlines!

我的解决方案是:


with open(filename) as f:
specify = [26, 30]
results = list(
map(lambda line: line[1],
filter(lambda line: line[0] in specify,
enumerate(f))
)
)

6.5G文件进行如下测试:

import time


filename = 'a.txt'
start = time.time()
with open(filename, 'w') as f:
for i in range(10_000_000):
f.write(f'{str(i)*100}\n')
end1 = time.time()


with open(filename) as f:
specify = [26, 30]
results = list(
map(lambda line: line[1],
filter(lambda line: line[0] in specify,
enumerate(f))
)
)
end2 = time.time()
print(f'write time: {end1-start}')
print(f'read time: {end2-end1}')
# write time: 14.38945460319519
# read time: 8.380386352539062

您可以使用一种最简单的逻辑将字符串拆分为数组或List。

f = open('filepath')
r = f.read()
s = r.split("\n")
n = [linenumber1, linenumber2] # [26, 29] in your
#case
for x in n:
print(s[x-1])
f.close()