这有效:
f = File.new("myfile").readlines
f[0] #=> "line 1"
f[21] #=> "line 22"
但是,如果我有一个非常大的文件,只需要阅读几行。是否有可能寻找特定的行并在Ruby中读取它们,而无需将文件加载到数组中?
我知道IO流,其中(如stdin的情况)你不能随意搜索流。当然必须有一种方法可以在不加载整个文件的情况下执行此操作。
答案 0 :(得分:7)
不要忽略IO
类。 IO::foreach
是返回枚举器的方法之一,可以进行延迟评估。
IO#each_line
也是另一个将返回枚举器的人。
在Ruby 2.0中,我们可以调用.lazy
并使用那些方法(zip和cycle除外),这些方法允许我们遍历枚举而不将整个文件放入内存。
答案 1 :(得分:5)
出于此目的,您可以使用each_line
迭代器与with_index
结合使用当前行的行号(从0开始计算):
File.open('myfile') do |file|
file.each_line.with_index do |line, lineno|
case lineno
when 0
# line 1
when 21
# line 22
end
end
end
通过使用open
,将块传递给它而不是new
,可以保证在块执行结束时正确关闭文件。
更新 with_index
方法接受一个可选参数来指定要使用的起始索引,因此上面的代码可以更好地编写如下:
file.each_line.with_index(1) do |line, lineno|
case lineno
when 1
# line 1
end
end
答案 2 :(得分:2)
我使用过Jack和toro2k的答案(大致相同的答案),但是根据我自己的用例进行了修改。我可能想要的地方:打开一个文件,并寻找多个随机行,其中顺序可能并不总是顺序的。这就是我提出的(抽象的):
class LazyFile
def initialize(file)
@content = File.new(file)
end
def [](lineno)
@content.rewind if @content.lineno > lineno
skip = lineno - @content.lineno
skip.times { @content.readline }
@content.readline
end
end
file = LazyFile("myfile")
file[1001]