创建线程安全的临时文件名

时间:2012-12-09 13:21:24

标签: ruby thread-safety filenames temp

使用Tempfile时,Ruby正在创建一个具有线程安全和进程间安全名称的文件。我只需要这样的文件名。

我想知道是否有更直接的方法:

t = Tempfile.new(['fleischwurst', '.png'])
temp_path = t.path
t.close
t.unlink

4 个答案:

答案 0 :(得分:55)

挖掘tempfile.rb您会注意到Tempfile包含Dir::Tmpname。在里面,你会找到make_tmpname来完成你所要求的。

Dir::Tmpname.make_tmpname "/tmp/źdźbło", nil
# => "/tmp/źdźbło20121209-1867-1qyptqe"
Dir::Tmpname.make_tmpname(['a', '.png'], nil)
# => "a20121209-2710-wcjbzr.png"

在同一个文件中,还有Dir::Tmpname.create,根据您要实现的目标,它会比make_tmpname稍微多一点。特别是,它确定了要使用的临时目录(假设你不在{nix,其中/tmp是一个全局正确的假设)。尽管如此,它还是有点丑陋,因为它需要一个块:

Dir::Tmpname.create(['a', '.png']) { }
# => "/tmp/a20140224-15930-l9sc6n.png"

该块用于测试文件是否存在的代码并引发Errno::EEXIST,以便生成一个新名称,并在末尾标记增量值。

答案 1 :(得分:0)

由于只需要文件名,因此使用SecureRandom会怎样:

require 'securerandom'

filename =  "#{SecureRandom.hex(6)}.png" #=> "0f04dd94addf.png"

您也可以使用SecureRandom.alphanumeric

答案 2 :(得分:0)

由于Dir::Tmpname.make_tmpnameremoved in Ruby 2.5.0,因此此后退到使用SecureRandom

require "tmpdir"

def generate_temp_filename(ext=".png")
  filename = begin
    Dir::Tmpname.make_tmpname(["x", ext], nil)
  rescue NoMethodError
    require "securerandom"
    "#{SecureRandom.urlsafe_base64}#{ext}"
  end
  File.join(Dir.tmpdir, filename)
end

答案 3 :(得分:-2)

我发现Dir:Tmpname解决方案对我不起作用。评估时:

Dir::Tmpname.make_tmpname "/tmp/blob", nil

在MRI Ruby 1.9.3p194下,我得到:

uninitialized constant Dir::Tmpname (NameError)

在JRuby 1.7.5(1.9.3p393)下,我得到:

NameError: uninitialized constant Dir::Tmpname

您可以尝试这样的事情:

def temp_name(file_name='', ext='', dir=nil)
    id   = Thread.current.hash * Time.now.to_i % 2**32
    name = "%s%d.%s" % [file_name, id, ext]
    dir ? File.join(dir, name) : name
end