如果我通过Tempfile
创建了一个临时文件,除了将它复制到另一个我可以使其成为“永久”的文件外,还有什么方法吗?我想避免在关联的Tempfile
实例被垃圾收集或流程终止时被删除。
在相关的一点上,有没有办法利用Tempfile
机制(或使用类似的机制)来获取“新”文件名而无需以该名称创建文件?
答案 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
。