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

Pet*_*vin 21 ruby temporary-files

如果我已经创建了一个临时文件Tempfile,除了将它复制到另一个文件,我可以使它"永久"吗?我想避免在关联的Tempfile实例被垃圾收集或终止进程时被删除.

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

Lin*_*ios 20

并不是的.对于问题本身,请看:

ObjectSpace.undefine_finalizer(tmpfile)
Run Code Online (Sandbox Code Playgroud)

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!
$ 
Run Code Online (Sandbox Code Playgroud)

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


至于你的第二个问题,请从这里尝试以下代码:

Dir::Tmpname.create('your_application_prefix') { |path| puts path }
Run Code Online (Sandbox Code Playgroud)

它需要一个require "tmpdir".


Pat*_*ity 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')
Run Code Online (Sandbox Code Playgroud)

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

  • 难道你不能只是复制文件而不是搞乱终结器,我想知道吗? (2认同)
  • @SergioTulentsev也是我最初的想法,但问题是明确的"除了复制"之外的方式. (2认同)