我正在读取一个10MB大小的文件,其中包含一些ID。我把它们读成红宝石列表。我担心它可能会在将来导致内存问题,当文件中的id数量可能会增加时。有批量阅读大文件的有效方法吗?红宝石 - 批量读取文件
谢谢
我正在读取一个10MB大小的文件,其中包含一些ID。我把它们读成红宝石列表。我担心它可能会在将来导致内存问题,当文件中的id数量可能会增加时。有批量阅读大文件的有效方法吗?红宝石 - 批量读取文件
谢谢
没有通用的方法。
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比第一种方法
慢随着Lazy Enumerators和each_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
我依稀记得这是我一直在寻找的答案。正确的方式来读取文件! – 2017-01-02 21:45:28
它应该如何工作?使用“懒惰”的目的是什么? – Ilya 2017-08-10 12:16:09
我做了大量数据的基准测试,内存使用情况与不使用'.lazy.each_slice'链一样。 – Ilya 2017-08-10 12:17:28