首页 > 解决方案 > Python 文件 read() 和 readline() 计数器?

问题描述

看起来 python 会跟踪 read() 和 readline() 的每次运行。它是增量的,通过到达运行,最后,它不返回任何值。如何找到这个计数器,并随时读取特定行?

编辑:我的目标是读取一个大小为几 Gb、数十万行的大文件。如果这是一个迭代器,那么它是不够的,我不想将整个文件加载到内存中。如何跳转到特定行而不必阅读不必要的行?

一个只有 3 行的文本文件。

# cat sample.txt
This is a sample text file. This is line 1
This is line 2
This is line 3

# python
Python 3.7.5 (default, Nov  7 2019, 10:50:52)
[GCC 8.3.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> file = open('sample.txt', 'r')
>>> file.readline()
'This is a sample text file. This is line 1\n'
>>> file.readline()
'This is line 2\n'
>>> file.readline()
'This is line 3\n'
>>> file.readline()
''
>>> file.readline()
''
>>> file.read()
''
>>> file.read(0)
''
>>> file.read()
''
>>>

# python
Python 3.7.5 (default, Nov  7 2019, 10:50:52)
[GCC 8.3.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> file = open('sample.txt', 'r')
>>> file.read()
'This is a sample text file. This is line 1\nThis is line 2\nThis is line 3\n'
>>> file.read()
''
>>> file.readline()
''
>>>

标签: pythonpython-3.xfile

解决方案


Python 中的文件对象是一个迭代器,迭代文件中的不同行。您可以使用readlines()一次将所有(剩余)行读取到列表中,或者read()读取文件中的单个或所有(剩余)字符(默认为全部,使用参数来读取要读取的字符数),但是默认行为(如果您直接迭代文件)与 with 相同readline,即从文件中产生下一行。

您可以将其与enumerate获得另一个迭代器产生行号以及每行(0除非您指定enumerate'sstart参数,否则第一行具有编号),或获取特定行:

>>> f = open("test.txt")
>>> lines = enumerate(f)
>>> next(lines)
(0, 'first line\n')
>>> next(lines)
(1, 'second line\n')
>>> next(lines)
(2, 'third line\n')

>>> f = open("test.txt")
>>> lines = enumerate(f)
>>> next(l for i, l in lines if i == 3)
'fourth line\n'

还有seek一种方法,可用于跳转到文件中的特定字符,这对于将文件“重置”到第一个位置很有用(或者重新打开它),但对查找特定字符没有多大帮助行,除非您知道每行的确切长度。(见下文)

如果您想“以任何顺序读取任何行”,最简单的方法是使用实​​际将所有行读入列表readlines,然后访问该列表中的项目(前提是您的文件不是太大)。

>>> f = open("test.txt")
>>> lines = f.readlines()
>>> lines[3]
'fourth line\n'
>>> lines[1]
'second line\n'

我的目标是读取几 Gb 大小、数十万行的大文件。

由于 Python 要知道一行的结束位置以及特定行的开始位置的唯一方法是计算\n它遇到的字符数,因此无法读取整个文件。如果文件非常大,并且您必须无序地重复读取行,则一次读取一行可能是有意义的将每行的起始位置存储在字典中。之后,您可以使用seek快速跳转到然后阅读特定行。

f = open("test.txt")
total = 1
lines = {}
for i, line in enumerate(f):
    lines[i] = total - 1
    total += len(line)
# jump to and read individual lines
f.seek(lines[3])
print(f.readline())
f.seek(lines[0])
print(f.readline())

推荐阅读