【问题标题】:Splitting huge file based on contents with ruby使用 ruby​​ 根据内容拆分大文件
【发布时间】:2010-11-30 05:26:27
【问题描述】:

免责声明:我不是程序员,从来没有,从来没有学过算法、CS 等。只需要使用它即可。

我的问题是:我需要根据第一个字段将一个巨大的(超过 4 GB)CSV 文件拆分为较小的文件(然后使用 require 'win32ole' 处理它)。在 awk 中这很容易:

awk -F ',' '{myfile=$1 ; print $0 >> (myfile".csv")}' KNAGYFILE.csv

但是ruby 我做到了:

open('hugefile').each { |hline|
    accno = hline[0,12]
    nline = hline[13,10000].gsub(/;/,",")
    accfile = File.open("#{accno.to_s}.csv", "a")
    accfile.puts nline
    accfile.close
}

然后认识到它的资源效率低下(几个文件打开/关闭)。我确信有更好的方法可以做到这一点,你能解释一下吗?

更新: 只是忘了提及,文件在第一列排序。例如。如果这是大文件:

012345678901,1,1,1,1,1,1
012345678901,1,2,1,1,1,1
012345678901,1,1,A,1,1,1
012345678901,1,1,1,1,A,A
A12345678901,1,1,1,1,1,1
A12345678901,1,1,1,1,1,1
A12345678901,1,1,1,1,1,1
A12345678901,1,1,1,1,1,1

然后我需要两个新文件,分别命名为 012345678901.csvA12345678901.csv

【问题讨论】:

  • 注意,你可能想要“hline[13..-1]”而不是“hline[13,10000]”,除非你特别想在 10013 个字符处截断你的行。
  • 哇,你说你不是程序员而且有 16k 的代表!太棒了。

标签: ruby optimization csv io split


【解决方案1】:

这应该可以解决多重打开-写入-关闭问题,尽管如果文件数量变大可能会遇到问题;我不能说,我从来没有打开过数百个文件供写入!

第一行是重要的:对于遇到的每个新密钥,它都会打开一个新文件并将其与该密钥存储在哈希中。最后一行关闭所有打开的文件。

files = Hash.new { |h, k| h[k] = File.open("#{k}.csv", 'w+') }
open('hugefile').each do |hline|
  files[hline[0,12]].puts hline[13,10000].gsub(/;/,",")
end
files.each { |n, f| f.close }

【讨论】:

  • 有趣的解决方案。我也会在工作中对其进行基准测试。 (是的,我需要打开大约 2000 个文件。)
  • 哎呀! 2000个文件?我只是想 - 输入是否排序?如果是这样,格伦的解决方案可能是最优的。
  • Mike 的解决方案更像是“Ruby 方式”。如果同时保持 2000 个打开的文件句柄会产生性能问题,您可以扩展 files 哈希功能以在文件变得太大时关闭一些文件。如果对输入进行排序,这一切都太过分了。
【解决方案2】:

您的 awk 解决方案必须多次打开文件,所以我认为您会得到相同的资源使用情况。

您可以在 $1 更改之前保持文件打开:

prev = nil
File.foreach('hugefile') do |hline|
  accno = hline[0,12]
  nline = hline[13,10000].gsub(/;/,",")
  if prev != accno
    accfile.close rescue nil
    accfile = File.open("#{accno.to_s}.csv", "a")
    prev = accno
  end
  accfile.puts nline
end

【讨论】:

  • AWK 是否在其处理的每一行重新打开(并关闭)文件?无论如何 - 谢谢你的回答,我会在工作中测试它,但是,它看起来是我想要的。
  • 不,我的意思是当你“打印 $0 >> somefile”时,它将打开、附加和关闭文件。
  • 我明白了,但我的 awk 解决方案适用于 IMO 的每一行。
  • 我只是在阅读 nawk 手册页(针对不同的问题),发现输出重定向仅在文件尚未打开的情况下打开文件,并保持打开状态直到显式关闭。因此,为 awk +1。
猜你喜欢
  • 1970-01-01
  • 2015-03-24
  • 2017-04-27
  • 1970-01-01
  • 1970-01-01
  • 2018-06-26
  • 2015-11-14
  • 1970-01-01
  • 2012-01-22
相关资源
最近更新 更多