2010-06-02 84 views
2

我正在讀取一個10MB大小的文件,其中包含一些ID。我把它們讀成紅寶石列表。我擔心它可能會在將來導致內存問題,當文件中的id數量可能會增加時。有批量閱讀大文件的有效方法嗎?紅寶石 - 批量讀取文件

謝謝

回答

3

沒有通用的方法。

1)你可以通過閱讀文件塊:

File.open('filename','r') do |f| 
    chunk = f.read(2048) 
    ... 
end 

缺點:你可以錯過一個字符串,如果它會是塊之間,也就是你尋找「SOME_TEXT」,而是「SOME_」是最後5個字節第一2048字節的塊,並且「TEXT」是一個4個字節的第二組塊的

2)可以讀取文件中的行由行

File.open('filename','r') do |f| 
    line = f.gets 
    ... 
end 

缺點:這樣它會是2x..5x比第一種方法

9

慢隨着Lazy Enumeratorseach_slice,你可以得到兩全其美。您不需要擔心中間的切割線,並且可以批量迭代多行。 batch_size可以自由選擇。

header_lines = 1 
batch_size = 2000 

File.open("big_file") do |file| 
    file.lazy.drop(header_lines).each_slice(batch_size) do |lines| 
    # do something with batch of lines 
    end 
end 

它可以被用於導入一個巨大的CSV文件導入數據庫:

require 'csv' 
batch_size = 2000 

File.open("big_data.csv") do |file| 
    headers = file.first 
    file.lazy.each_slice(batch_size) do |lines| 
    csv_rows = CSV.parse(lines.join, write_headers: true, headers: headers) 
    # do something with 2000 csv rows, e.g. bulk insert them into a database 
    end 
end 
+1

我依稀記得這是我一直在尋找的答案。正確的方式來讀取文件! – 2017-01-02 21:45:28

+0

它應該如何工作?使用「懶惰」的目的是什麼? – Ilya 2017-08-10 12:16:09

+0

我做了大量數據的基準測試,內存使用情況與不使用'.lazy.each_slice'鏈一樣。 – Ilya 2017-08-10 12:17:28