簡體   English   中英

有沒有辦法在不將整個內容加載到數組中的情況下搜索文件?

[英]Is there a way to seek through a file without loading the whole thing into an array?

這有效:

f = File.new("myfile").readlines
f[0] #=> "line 1"
f[21] #=> "line 22"

但是,如果我有一個非常大的文件,只需要閱讀幾行。 有沒有可能尋找特定的行並在Ruby中讀取它們,而無需將文件加載到數組中?

我知道IO流,在那里(如在stdin的情況下)你不能隨機搜索流。 當然必須有一種方法可以在不加載整個文件的情況下執行此操作。

不要忽略IO類。 IO::foreach是返回Enumerator的方法之一,可以進行延遲計算。

IO#each_line也是另一個將返回枚舉器的人。

在Ruby 2.0中,我們可以調用.lazy並使用那些方法,除了zip和cycle,它們允許我們遍歷枚舉而不將整個文件放入內存。

為此,您可以使用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

我使用過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]

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM