当使用Tempfile
Ruby 创建一个具有线程安全和进程间安全名称的文件时。这样我只需要一个文件名。
我想知道是否有比以下更直接的方法:
t = Tempfile.new(['fleischwurst', '.png'])
temp_path = t.path
t.close
t.unlink
当使用Tempfile
Ruby 创建一个具有线程安全和进程间安全名称的文件时。这样我只需要一个文件名。
我想知道是否有比以下更直接的方法:
t = Tempfile.new(['fleischwurst', '.png'])
temp_path = t.path
t.close
t.unlink
你可以使用Dir::Tmpname.create
. 它计算出要使用的临时目录(除非您将目录传递给它)。考虑到它需要一个块,使用起来有点难看:
require 'tmpdir'
# => true
Dir::Tmpname.create(['prefix-', '.ext']) {}
# => "/tmp/prefix-20190827-1-87n9iu.ext"
Dir::Tmpname.create(['prefix-', '.ext'], '/my/custom/directory') {}
# => "/my/custom/directory/prefix-20190827-1-11x2u0h.ext"
该块用于测试文件是否存在并引发代码,Errno::EEXIST
以便可以生成一个新名称,并在末尾附加递增值。
Ruby on Rails实现的解决方案很简短,与最初在 Ruby 中实现的解决方案相似:
require 'tmpdir'
# => true
File.join(Dir.tmpdir, "YOUR_PREFIX-#{Time.now.strftime("%Y%m%d")}-#{$$}-#{rand(0x100000000).to_s(36)}-YOUR_SUFFIX")
=> "/tmp/YOUR_PREFIX-20190827-1-wyouwg-YOUR_SUFFIX"
File.join(Dir.tmpdir, "YOUR_PREFIX-#{Time.now.strftime("%Y%m%d")}-#{$$}-#{rand(0x100000000).to_s(36)}-YOUR_SUFFIX")
=> "/tmp/YOUR_PREFIX-20190827-1-140far-YOUR_SUFFIX"
Dir::Tmpname.make_tmpname 在 Ruby 2.5.0 中被移除。在 Ruby 2.4.4 之前,它可以接受目录路径作为前缀,但从 Ruby 2.4.4 开始,目录分隔符被删除。
深入研究tempfile.rb
你会发现Tempfile
其中包括Dir::Tmpname
. 在里面你会发现make_tmpname
哪个可以满足你的要求。
require 'tmpdir'
# => true
File.join(Dir.tmpdir, Dir::Tmpname.make_tmpname("prefix-", nil))
# => "/tmp/prefix-20190827-1-dfhvld"
File.join(Dir.tmpdir, Dir::Tmpname.make_tmpname(["prefix-", ".ext"], nil))
# => "/tmp/prefix-20190827-1-19zjck1.ext"
File.join(Dir.tmpdir, Dir::Tmpname.make_tmpname(["prefix-", ".ext"], "suffix"))
# => "/tmp/prefix-20190827-1-f5ipo7-suffix.ext"
由于在 Ruby 2.5.0 中Dir::Tmpname.make_tmpname
被删除,这个回退到使用: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
由于您只需要文件名,因此使用SecureRandom怎么样:
require 'securerandom'
filename = "#{SecureRandom.hex(6)}.png" #=> "0f04dd94addf.png"
你也可以使用SecureRandom.alphanumeric
我发现 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