我正在解决一些小问题,并会就如何解决它提出一些建议: 给定具有未知列数和行数的csv文件,输出具有值的列列表以及每个值重复的次数。没有使用任何图书馆。
如果文件很小,这应该不是问题,但是当它是几个Gigs时,我得到NoMemoryError:无法分配内存。有没有办法创建一个哈希并从磁盘读取而不是将文件加载到内存?你可以用perl绑定Hashes
来做到这一点编辑:IO#foreach会将文件加载到内存中吗? File.open(filename).each怎么样?
答案 0 :(得分:21)
一次读取一行文件,随时丢弃每一行:
open("big.csv") do |csv|
csv.each_line do |line|
values = line.split(",")
# process the values
end
end
使用此方法,永远不会耗尽内存。
答案 1 :(得分: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
答案 2 :(得分:0)
为将来参考,在这种情况下,您想使用CSV.foreach('big_file.csv', headers: true) do |row|
这将以最小的内存占用量(不考虑文件大小,应小于1MB)从IO对象逐行读取文件。