2010-06-02 77 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