-4

有什么办法可以在不将所有内容加载到缓冲区的情况下读写文件?

4

4 回答 4

4

文件对象是可迭代的:

with open(filename) as f:
    for line in f:
        do_something(line)

迭代它们一次会产生 1 行(并且不会将整个文件存储在内存中)


编写文件同样简单:

with open(filename,'w') as f:
     for x in get_data():
         f.write(x)

或者您可以使用writelines传入生成器的方法。例如f.writelines(get_data())

其中get_data可以定义为:

def get_data():
    for i in xrange(200):
        yield '%d\n'%i
于 2012-12-18T15:47:07.193 回答
3

您可以使用seek for 转到要读取的文件部分。

来自文档:

要更改文件对象的位置,请使用 f.seek(offset, from_what)。位置是通过将偏移量添加到参考点来计算的;参考点由 from_what 参数选择。from_what 值为 0 从文件开头测量,1 使用当前文件位置,2 使用文件末尾作为参考点。from_what 可以省略,默认为 0,使用文件的开头作为参考点。

在寻找之后,您可以读取字节或行,就像您最初正常加载文件一样。

这是一个示例函数:

def special_read_file(filename, location, length):
    file_handle = open(filename)
    file_handle.seek(location, 0)
    return file_handle.read(length)

位置和长度以字节为单位。file_name 将是您要读取的文件的位置字符串。

你可以用 seek 做一些有趣的事情。使用它在文件中跳转,这样您就不必在本地存储文件内容,它仍然可以让您遍历行。

with正如其他一些答案已经提到的那样,使用和迭代文件行for line in file是保持系统内容轻松的好方法。但是传递一个 file_handle 要简单得多,您不必一直打开和关闭或读取它的一部分,您可以打开一个句柄,然后在需要该特定文件时从您需要的位置读取。

在这里,我写了一个生成器函数,它可以像往常一样工作,只有你可以指定从文件的哪个部分开始读取。

def read_handle_from(file_handle, start_point):
    file_handle.seek(start_point, 0)
    for line in file_handle:
        yield line

my_file_handle = open(file_name)
for line in read_handle_from(my_file_handle, 2000):
    #do stuff

您可以轻松地修改函数以限制读取的行数,或根据需要读取的字节数。

它很容易为自己创建函数和生成器以使用你想要的方式,不要害怕在 python 中创建你自己的函数,并不是所有的东西都需要内置。

于 2012-12-18T15:52:55.680 回答
1

文件对象是可迭代的,因此您可以随心所欲地使用它们。

例如,要从输入到输出每隔一行写入一次,请使用以下内容:

from itertools import islice
with open('input') as fin, open('output', 'w') as fout:
    every_other = islice(fin, None, None, 2)
    fout.writelines(every_other)
于 2012-12-18T15:59:21.240 回答
1

是的你可以。例如,下面一行一行地查看一个文件:

with open('data.txt') as f:
    for line in f:
        print line.strip()

这不会将整个文件加载到内存中。

于 2012-12-18T15:47:35.707 回答