TL; DR
所有文件和IO对象都存储在ObjectSpace中。
Answer
The 对象空间 http://www.ruby-doc.org/core-1.9.3/ObjectSpace.html类 说:
ObjectSpace 模块包含许多与垃圾收集工具交互的例程,并允许您使用迭代器遍历所有活动对象。
我是如何测试的
我在 Ruby 1.9.3p194 的控制台上对此进行了测试。
测试夹具非常简单。这个想法是让两个具有不同对象标识的 File 对象,但只有一个可以通过变量直接访问。另一个是“在外面的某个地方”。
# Don't save a reference to the first object.
filename='/tmp/foo'
File.open(filename)
filehandle = File.open(filename)
然后,即使我没有使用显式对象引用,我也探索了与 File 对象交互的不同方式。当我了解了 ObjectSpace 后,这变得非常简单。
# List all open File objects.
ObjectSpace.each_object(File) do |f|
puts "%s: %d" % [f.path, f.fileno] unless f.closed?
end
# List the "dangling" File object which we didn't store in a variable.
ObjectSpace.each_object(File) do |f|
unless f.closed?
printf "%s: %d\n", f.path, f.fileno unless f === filehandle
end
end
# Close any dangling File objects. Ignore already-closed files, and leave
# the "accessible" object stored in *filehandle* alone.
ObjectSpace.each_object(File) {|f| f.close unless f === filehandle rescue nil}
结论
可能还有其他方法可以做到这一点,但这是我为了解决自己的问题而想出的答案。如果您知道更好的方法,请发布另一个答案。世界将因它而变得更加美好。