【问题标题】:Go to a specific line in file转到文件中的特定行
【发布时间】:2017-10-09 16:44:03
【问题描述】:

for line in f: 期间,我的代码保存了包含特定数据的行。不幸的是,我必须阅读整个文件以确保它是最新的数据。 第二次,我必须检查整个文件(5000-8000 行之间),直到我得到正确的行(对于每个数据)。

所以,我的问题是,可以打开一个文件并转到特定行,阅读它并再次执行。我看到了不同的答案,但我无法将所有文件保存在 str 中,因为我的设备上没有那么多内存……这就是我想直接在文件中搜索的原因。

【问题讨论】:

  • 如果行具有固定大小或之前的行不改变,是的,通过计算/缓存文件中的行位置,否则这是不可能的。最好使用数据库或二进制文件。
  • 在 f 中使用 for line 时,使用生成器读取数据。所以整个文件永远不会一次加载到内存中。
  • 不幸的是,没有@Jean-FrançoisFabre,尺寸没有固定也无法固定。这是我的第一个想法。
  • @NM,我知道这一点,我想保留这个过程。这就是为什么我不想使用readlines()
  • 相关(但不重复):stackoverflow.com/questions/620367/…

标签: python python-2.7


【解决方案1】:

使用迭代器和生成器,文件xreadlines (python 2) 它是 惰性 评估的,因此在您使用文件之前不会将文件加载到内存中:

def drop_and_get(skiping, it):
    for _ in xrange(skiping):
        next(it)
    return next(it)
f = xrange(10000)#lets say your file is this generator
drop_and_get(500, iter(f))
500

所以你实际上可以做类似的事情:

with open(yourfile, "r") as f:
    your_line = drop_and_get(5000, f.xreadlines())
    print your_line

你甚至可以跳过xreadlines,因为文件对象本身就是一个迭代器

with open(yourfile, "r") as f:
    your_line = drop_and_get(5000, f)
    print your_line

【讨论】:

  • @Jean-FrançoisFabre,是的,但会解决内存问题,因为不应该将字符串存储在内存中。
  • 你不需要从文件句柄创建一个迭代器,它已经是一个了。
  • @Jean-FrançoisFabre,是的,它是为了使示例工作,但我会改变它。谢谢
  • @Jean-FrançoisFabre,f xrange 对象应转换为迭代器以使用它,试一试:D
  • 是的,我的错,你是对的。否则无法调用 next。但是使用文件句柄它可以工作。很公平。您可以将 python 3 兼容代码添加到您的示例中。
【解决方案2】:

丹尼尔解决方案非常好。一个更简单的替代方法是循环文件句柄并在到达所需行时中断。然后您可以恢复循环以实际处理这些行。

请注意,除非行的大小没有改变,否则没有奇迹(在这种情况下,您可以记住文件位置和seek):您必须从一开始就读取所有文件数据。您只是不需要使用readlines() 将其存储到内存中。永远不要使用readlines()

这是我的幼稚方法,不使用生成器或复杂的东西,但同样有效且简单:

# skip first 5000 lines
for i,line in enumerate(f):
    if i == 5000:
       break

# process the rest of the file
for line in f:
    print(line.rstrip())

【讨论】:

  • 您的解决方案不起作用,我的代码在第一个 for 循环后从头重新打开文件(使用 enumerate(f))。我当然忘记了什么。
  • 是的,试试打印循环,你会看到第 5000 行。
  • 我看到了第 5000 行,但第二个 for 循环从文件开头开始,而不是像我预期的那样第 5000 行。
  • 我刚刚用一个小文件进行了测试,它可以工作。当然,不要在重新分配f 之间重新打开文件。两个循环必须是连续的。
【解决方案3】:

下面,你可以找到我的代码:

with open(leases_file,'r') as f:
    for line in f:
        # save the line numbers
    for l in list_ip.values(): # do it for each line saved
        f.seek(0) # go back from the beginning
        for i, line in enumerate(f): 
            # Looking for the good line
            if q == (l-1): # l contain the line number
                break
        for line in f:
            # read the data 

我今天早上又试了一次,也许是因为我做了 'f.seek(0)' ?这是我和你的代码之间的唯一区别。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-01-20
    • 2010-10-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多