【问题标题】:dealing with large CSV files (20G) in ruby在 ruby​​ 中处理大型 CSV 文件(20G)
【发布时间】:2012-11-30 17:15:36
【问题描述】:

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

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

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

【问题讨论】:

  • 这是工作任务?显示您编写的代码。
  • 只是想知道...您是否因为没有任何解决方案有帮助而没有接受答案?还是另有原因?这个问题再次出现在我的活动中,我想知道。

标签: ruby parsing csv


【解决方案1】:

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

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

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

【讨论】:

    【解决方案2】:

    您是否一次阅读整个文件?逐行读取它,即使用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
    

    【讨论】:

    • 我正在寻找一个纯 ruby​​ 版本,但这很有帮助
    • @fenec,是什么让你认为这个版本不纯?
    • 哈哈哈可能是我不知道怎么用,怎么看文件
    • @fenec,根据所有定义,这是一个纯红宝石版本。
    • CSV 文件中的管道可能是导致它不是纯 Ruby 的部分。但这种方法同样适用于File.open 发起的数据流
    【解决方案3】:

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

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-02-20
      • 1970-01-01
      • 2015-10-10
      • 2018-02-23
      • 2012-05-30
      • 1970-01-01
      • 2017-07-05
      相关资源
      最近更新 更多