用Ruby检索文件



所以我要做的是将文件名传递到方法中,并检查文件是否关闭。我正在努力做的是从文件名中获得一个文件对象,而不实际打开文件。

def file_is_closed(file_name)
  file = # The method I am looking for
  file.closed?
end

我必须填写注释部分。我尝试使用load_file方法从YAML模块,但我认为,给出了文件的内容,而不是实际的文件。

我在File模块中找不到要调用的方法。有没有我不知道的方法?

File#closed?返回特定File对象是否关闭,因此没有方法可以使当前尝试的解决方案工作:

f1 = File.new("test.file")
f2 = File.new("test.file")
f1.close
f1.closed? # => true # Even though f2 still has the same file open

如果可能的话,最好保留你正在使用的File对象,以便询问它是否已关闭。

如果你真的想知道你当前的Ruby进程是否为某个特定路径打开了任何File对象,像这样的东西感觉有点像黑客,但应该大部分工作:

def file_is_closed?(file_name)
  ObjectSpace.each_object(File) do |f|
    if File.absolute_path(f) == File.absolute_path(file_name) && !f.closed?
      return false
    end
  end
  true
end

我不赞成处理极端情况,但它似乎对我一般工作:

f1 = File.new("test.file")
f2 = File.new("test.file")
file_is_closed?("test.file") # => false
f1.close
file_is_closed?("test.file") # => false
f2.close
file_is_closed?("test.file") # => true

如果你想知道任何进程是否打开了文件,我认为你需要求助于外部的东西,如lsof

对于那些您不再能够访问Ruby中的原始文件对象的情况(例如,在fork + exec之后),可以在/proc/pid/fd中获得打开的文件描述符列表这里的每个文件都以文件描述符编号命名,并且是指向打开的文件、管道或套接字的符号链接:

# Returns hash in form fd => filename
def open_file_descriptors
  Hash[
  Dir.glob( File.join( '/proc', Process.pid.to_s, 'fd', '*' ) ).
    map { |fn| [File.basename(fn).to_i, File.readlink(fn)] rescue [nil, nil] }.
    delete_if { |fd, fn| fd.nil? or fd < 3 }
  ]
end
# Return IO object for the named file, or nil if it's not open
def io_for_path(path)
  fd, fn = open_file_descriptors.find {|k,v| path === v}
  fd.nil? ? nil : IO.for_fd(fd)
end
# close an open file
file = io_for_path('/my/open/file')
file.close unless file.nil?

open_file_descriptors方法解析fd目录并返回类似{3 => '/my/open/file'}的散列。然后,获取所需文件的文件描述符号是一件简单的事情,并让Ruby使用for_fd为它生成一个IO对象。

最新更新