【发布时间】:2011-05-22 19:06:49
【问题描述】:
有没有在 Ruby 中就地读取、编辑和写入文件的好方法?
在我的在线搜索中,我发现建议将其全部读入数组,修改所述数组,然后将所有内容写出。我觉得应该有更好的解决方案,尤其是在我处理一个非常大的文件时。
类似:
myfile = File.open("path/to/file.txt", "r+")
myfile.each do |line|
myfile.replace_puts('blah') if line =~ /myregex/
end
myfile.close
replace_puts 将覆盖当前行,而不是像当前那样(覆盖)写下一行,因为指针位于行尾(分隔符之后)。
那么匹配/myregex/ 的每一行都将被替换为'blah'。显然,就处理而言,我的想法比这更复杂,并且会在一行中完成,但想法是一样的 - 我想逐行读取文件,并编辑某些行,并且写完就写出来。
也许有一种方法可以说“倒回到最后一个分隔符之后”?或者使用each_with_index 并通过行索引号写入的某种方式?不过,我找不到任何类似的东西。
到目前为止,我最好的解决方案是逐行读取内容,将它们逐行写入新的(临时)文件(可能已编辑),然后用新的临时文件覆盖旧文件并删除。同样,我觉得应该有更好的方法 - 我认为我不应该创建一个新的 1gig 文件来编辑现有 1GB 文件中的一些行。
【问题讨论】:
-
如果要读取然后覆盖的代码在过程中途失败,请考虑结果:您将面临破坏文件的风险。
-
好的,作为后续问题:从命令行,您可以这样做:ruby -pe "gsub(/blah/,'newstuff')" whatev.txt。这就是我想做的,但我不想在命令行上那样做,我想把它放在更大的东西里。谁能告诉我,在内部,该命令在做什么会产生逐行编辑文件的错觉?它是写入临时文件还是使用数组?因为它似乎可以相当快地处理相当大的文件,比这里提供的建议要快。
-
这是个好问题。你能把它变成一个新问题吗?这使得其他人更容易看到它并回答它。另外,如果这个问题的回答令您满意,您能接受这个答案吗?谢谢!
-
虽然逐行读取文件并写入新文件似乎效率低下,但实际上the speed is equal-to or better-than trying to read a huge file into memory,修改它并将其写回。这样做是一种公认的编程实践,而且,不,一旦考虑到速度、内存要求和数据安全性,确实没有更好的解决方案。