所以我想做的是将文件名传递给方法并检查文件是否已关闭。我正在努力做的是从文件名中获取文件对象而不实际打开文件。
def file_is_closed(file_name)
file = # The method I am looking for
file.closed?
end
我必须填写评论部分。我尝试使用 YAML 模块中的 load_file 方法,但我认为这给出了文件的内容而不是实际文件。
我在 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 对象,这样的事情感觉很hack-ish但应该主要工作:
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 为它生成一个 IO 对象for_fd
。
当然,这假设您使用的是 Linux。