9

我试图搜索这个,但找不到太多。这似乎是以前可能被问过的问题(很多次?),所以如果是这样的话,我很抱歉。

我想知道在 Ruby 中解析文件某些部分的最快方法是什么。例如,假设我知道我想要的特定函数的信息位于 1000 行文件的第 500 行和第 600 行之间。(显然这种问题是针对很多大文件的,我只是使用那些较小的数字来举例),因为我知道它不会在上半年,有没有一种快速的方法来忽略这些信息?

目前我正在使用以下内容:

while  buffer = file_in.gets and file_in.lineno <600
  next unless file_in.lineno > 500
  if buffer.chomp!.include? some_string
    do_func_whatever
  end
end

它有效,但我不禁认为它可以更好地工作。

我对 Ruby 非常陌生,并且有兴趣在其中学习新的做事方式。

4

4 回答 4

11
file.lines.drop(500).take(100) # will get you lines 501-600

通常,您不能避免从头开始读取文件,直到您感兴趣的行,因为每一行的长度可能不同。但是,您可以避免的一件事是将整个文件加载到一个大数组中。只需逐行阅读,计数,然后丢弃它们,直到达到您要查找的内容。很像你自己的例子。你可以让它更红宝石。

PS。铁皮人的评论让我做了一些实验。虽然我没有找到加载整个文件的任何理由drop,但确实存在一个问题:将文件的其余部分drop 返回到一个数组中。这是一种可以避免的方法:

file.lines.select.with_index{|l,i| (501..600) === i}

PS2:Doh,上面的代码虽然没有创建一个巨大的数组,但会遍历整个文件,甚至是 600 以下的行。:(这是第三个版本:

enum = file.lines
500.times{enum.next} # skip 500
enum.take(100) # take the next 100

或者,如果您更喜欢 FP:

file.lines.tap{|enum| 500.times{enum.next}}.take(100)

无论如何,这个独白的好处是你可以学习多种方法来迭代一个文件。;)

于 2011-02-19T19:10:35.160 回答
1

我不知道是否有对行执行此操作的等效方法,但是您可以使用seekoffsetIO 对象上的参数来“跳过”字节。

请参阅IO#seek,或参阅IO#open以获取有关 offset 参数的信息。

于 2011-02-19T18:12:03.673 回答
0

听起来rio在这里可能会有所帮助。它为您提供了一种lines()方法。

于 2011-02-19T18:07:31.783 回答
0

您可以使用IO#readlines,它返回一个包含所有行的数组

IO.readlines(file_in)[500..600].each do |line| 
  #line is each line in the file (including the last \n)
  #stuff
end

或者

f = File.new(file_in)
f.readlines[500..600].each do |line| 
  #line is each line in the file (including the last \n)
  #stuff
end
于 2011-02-19T18:09:13.460 回答