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

问题描述 投票:0回答:3

如果我通过

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

在相关点上,有没有办法利用

Tempfile
机制(或使用类似的机制)来获取“新”文件名,而不必以该名称创建文件?

ruby temporary-files
3个回答
28
投票

其实不然。对于问题本身,请参阅:

ObjectSpace.undefine_finalizer(tmpfile)

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

$ 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
,操作系统每隔一段时间就会自动清理一次(例如 每次启动时)。因此,即使您“保留”该文件,您也需要接受它的消失,或者将其移动到默认情况下不会被清除的目录,例如
/var/tmp
(用于持久临时文件的 Linux 目录)文件)。


至于你的第二个问题,请尝试here中的代码:

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

它需要一个

require "tmpdir"


13
投票

我认为最简单的解决方案可能是对

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


0
投票

就我而言,我尝试使用

ObjectSpace.undefine_finalizer(t)
,但它对我来说失败了(我认为可能是由于垃圾收集器在请求完成后,只是从 tmp 文件夹中获取所有内容)。所以我只是做了一些简单有效的事情,将其移到 tmp 文件夹之外

  t = Tempfile.new("test")

  # Extra validation, check if new path is empty & clear it 
  FileUtils.rm(new_path) if File.file?(new_path)

  # Persisting the file
  FileUtils.mv(t.path, new_path)

一切顺利! 👍🏼(如果您检查该新文件夹,该文件应该永远存在)

记得稍后清理它,可能就像我在预验证中所做的那样

© www.soinside.com 2019 - 2024. All rights reserved.