如何处理Ruby中的大文件?

时间:2009-07-07 04:30:21

标签: ruby file-io

我对编程很陌生,所以要温柔。我正在尝试从库数据库.dat文件中提取IBSN编号。我编写的代码有效,但它只搜索180MB文件的大约一半。如何调整它来搜索整个文件?或者我如何编写一个程序,将dat文件拆分成可管理的块?

编辑:这是我的代码:

export = File.new("resultsfinal.txt","w+")

File.open("bibrec2.dat").each do |line|
  line.scan(/[a]{1}[1234567890xX]{10}\W/) do |x|
    export.puts x
  end
  line.scan(/[a]{1}[1234567890xX]{13}/) do |x|
    export.puts x
  end
end

6 个答案:

答案 0 :(得分:4)

您应该尝试捕获异常以检查问题是否确实存在于读取块上。

就是这样你知道我已经用类似的语法编写了一个脚本来搜索~8GB的真实大文件而没有问题。

export = File.new("resultsfinal.txt","w+")

File.open("bibrec2.dat").each do |line|
  begin
    line.scan(/[a]{1}[1234567890xX]{10}\W/) do |x|
      export.puts x
    end
    line.scan(/[a]{1}[1234567890xX]{13}/) do |x|
      export.puts x
    end
  rescue
    puts "Problem while adding the result"
  end
end

答案 1 :(得分:3)

最主要的是清理并结合正则表达式以获得性能优势。此外,您应始终对文件使用块语法,以确保正确关闭fd。 File#each不会将整个文件加载到内存中,它一次只执行一行:

File.open("resultsfinal.txt","w+") do |output|
    File.open("bibrec2.dat").each do |line|
        output.puts line.scan(/a[\dxX]{10}(?:[\dxX]{3}|\W)/)
    end
end

答案 2 :(得分:2)

file = File.new("bibrec2.dat", "r")
while (line = file.gets)
  line.scan(/[a]{1}[1234567890xX]{10}\W/) do |x|
    export.puts x
  end
  line.scan(/[a]{1}[1234567890xX]{13}/) do |x|
    export.puts x
  end
end
file.close

答案 3 :(得分:1)

至于性能问题,我看不出任何特别担心文件大小的问题:180MB不应该造成任何问题。运行脚本时内存使用会发生什么变化?

但是,我不确定您的正则表达式是否正在执行您想要的操作。例如:

/[a]{1}[1234567890xX]{10}\W/

(我认为)这个:

  • 一个“a”。你真的想要匹配“a”吗?在这种情况下,“a”就足够了,而不是“[a] {1}”。
  • 正好10(数字或“x”或“X”)
  • 单个“非单词”字符,即不是a-z,A-Z,0-9或下划线

有几个样本ISBN匹配器herehere,虽然它们似乎匹配的东西更像我们在书的封底上看到的格式,我猜你的输入文件已经删除了一些格式化。

答案 4 :(得分:1)

您可以查看使用File#truncateIO#seek并使用二进制搜索类型算法。 #truncate可能具有破坏性,因此您应该复制该文件(我知道这很麻烦)。

middle = File.new("my_huge_file.dat").size / 2
tmpfile = File.new("my_huge_file.dat", "r+").truncate(middle)
# run search algoritm on 'tmpfile'
File.open("my_huge_file.dat") do |huge_file|
  huge_file.seek(middle + 1)
  # run search algorithm from here
end

代码高度未经测试,易碎且不完整。但我希望它能为你提供一个平台。

答案 5 :(得分:-2)

如果您在现代操作系统上进行编程并且计算机有足够的内存(比如512megs),Ruby应该可以将整个文件读入内存。

当您在典型的32位操作系统上获得大约2 GB的工作集时,通常会遇到麻烦。