6

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

如果文件很小,这应该不是问题,但是当它是几个 Gig 时,我得到 NoMemoryError: failed to allocate memory。有没有办法创建哈希并从磁盘读取而不是将文件加载到内存?你可以在 perl 中使用绑定的哈希来做到这一点

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

4

3 回答 3

21

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

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

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

于 2012-12-12T22:46:31.133 回答
6

您是否一次阅读整个文件?逐行读取它,即使用ruby -pe,ruby -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
于 2012-12-12T22:22:35.287 回答
1

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

这将以最小的内存占用从 IO 对象中逐行读取文件(无论文件大小如何,都应低于 1MB)。

于 2020-08-11T10:21:07.957 回答