在ruby中处理大型CSV文件(20G)

时间:2012-12-12 21:49:14

标签: ruby parsing csv

我正在解决一些小问题,并会就如何解决它提出一些建议: 给定具有未知列数和行数的csv文件,输出具有值的列列表以及每个值重复的次数。没有使用任何图书馆。

如果文件很小,这应该不是问题,但是当它是几个Gigs时,我得到NoM​​emoryError:无法分配内存。有没有办法创建一个哈希并从磁盘读取而不是将文件加载到内存?你可以用perl绑定Hashes

来做到这一点

编辑:IO#foreach会将文件加载到内存中吗? File.open(filename).each怎么样?

3 个答案:

答案 0 :(得分:21)

一次读取一行文件,随时丢弃每一行:

open("big.csv") do |csv|
  csv.each_line do |line|
    values = line.split(",")
    # process the values
  end
end

使用此方法,永远不会耗尽内存。

答案 1 :(得分:6)

您是否一次阅读整个文件?以每行为基础读取它,即使用ruby -peruby -ne$stdin.each应减少已处理的垃圾收集行的内存使用量。

data = {}
$stdin.each do |line|
  # Process line, store results in the data hash.
end

将其另存为script.rb并将巨大的CSV文件传输到此脚本的标准输入中:

ruby script.rb < data.csv

如果您不想阅读标准输入,我们需要进行一些小改动。

data = {}
File.open("data.csv").each do |line|
  # Process line, store results in the data hash.
end

答案 2 :(得分:0)

为将来参考,在这种情况下,您想使用CSV.foreach('big_file.csv', headers: true) do |row|

这将以最小的内存占用量(不考虑文件大小,应小于1MB)从IO对象逐行读取文件。