Ruby - 批量读取文件

问题描述 投票:0回答:4

我正在读取一个大小为 10mb 且包含一些 id 的文件。我将它们读入红宝石列表中。我担心将来当文件中的 id 数量可能增加时,它可能会导致内存问题。有没有有效的批量读取大文件的方法?

谢谢你

ruby-on-rails ruby scripting
4个回答
44
投票

使用 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, headers: headers)
    # do something with 2000 csv rows, e.g. bulk insert them into a database
  end
end

12
投票

没有通用的方法。

1)您可以按块读取文件:

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

缺点:如果子字符串位于块之间,则可能会丢失子字符串,即您查找“SOME_TEXT”,但“SOME_”是第一个 2048 字节块的最后 5 个字节,而“TEXT”是 4 个字节第二块

2)您可以逐行读取文件

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

缺点:这样会比第一种方法慢 2x..5x


0
投票

基于@Eric Duminil 的回答。 CSV 类还直接支持惰性枚举器。

require 'csv'
batch_size   = 2000

csv = CSV.open("big_data.csv", headers: true)
csv.lazy.each_slice(batch_size) do |csv_rows|
  # do something with 2000 csv rows, e.g. bulk insert them into a database
end

这种方法的好处是我们可以获得已经解析的 CSV 行。


-1
投票

如果您非常担心速度/内存效率,您是否考虑过使用 shell 并使用

grep
awk
sed
等?如果我对输入文件的结构以及您要提取的内容有更多了解,我可能会为您构建一个命令。

© www.soinside.com 2019 - 2024. All rights reserved.