有没有办法使Ruby临时文件永久化?

时间:2014-01-22 14:19:14

标签: ruby temporary-files

如果我通过Tempfile创建了一个临时文件,除了将它复制到另一个我可以使其成为“永久”的文件外,还有什么方法吗?我想避免在关联的Tempfile实例被垃圾收集或流程终止时被删除。

在相关的一点上,有没有办法利用Tempfile机制(或使用类似的机制)来获取“新”文件名而无需以该名称创建文件?

2 个答案:

答案 0 :(得分:19)

不是真的。对于问题本身,请参阅:

ObjectSpace.undefine_finalizer(tmpfile)

Tempfile库使用Ruby ObjectSpace终结器在垃圾收集时自动删除自身。通过使用上面的行,您可以删除Tempfile删除自身的能力,如果您不删除它。所以,例如:

$ irb
2.0.0p0 :001 > require "tempfile"
 => true 
2.0.0p0 :002 > t = Tempfile.new("test")
 => #<Tempfile:/tmp/test20140122-6655-80p4b7> 
2.0.0p0 :003 > t.write("Hi!")
 => 3 
2.0.0p0 :004 > ObjectSpace.undefine_finalizer(t)
 => #<Tempfile:/tmp/test20140122-6655-80p4b7> 
2.0.0p0 :005 > exit
$ cat /tmp/test20140122-6655-80p4b7
Hi!
$ 

但是还有其他事情需要注意。 Tempfile将使用系统临时文件目录,如/tmp,操作系统会每隔一段时间自动清除一次(例如on every boot)。因此,即使您“持久化”该文件,您也需要确定它正在消失,或者将其移动到默认情况下未清除的目录,例如/var/tmp(Linux目录为持久的临时文件)。


关于您的第二个问题,请尝试here中的此代码:

Dir::Tmpname.create('your_application_prefix') { |path| puts path }

需要require "tmpdir"

答案 1 :(得分:8)

我认为最简单的解决方案可能是修补Tmpfile类以添加persist方法。此方法采用临时文件将移动到的文件名。此外,它会删除终结器,以便在退出时不会删除临时文件。

require 'tempfile'
require 'fileutils'

class Tempfile
  def persist(filename)
    FileUtils.mv(self.path, filename)
    ObjectSpace.undefine_finalizer(self)
  end
end

file = Tempfile.new('tmp')
file.write('hello world')
file.close
file.persist('hello.txt')

运行此程序将通过移动原始临时文件而不是复制它来创建持久文件./hello.txt