Ruby的文档报告说,将File.open与块一起使用会自动关闭文件,否则建议使用close方法显式关闭文件。 据说,如果有人忘记在后一种情况下关闭文件,该文件将保持打开状态。如何检查文件是否仍然打开并最终关闭?
如果我决定使用IO类打开文件并使用IO.new(fd)创建新的I / O流:
fd = IO.sysopen("file.txt", "a")
myios = IO.new(fd)
myios.puts "new line"
一旦执行代码,流会自动关闭吗?我怎么检查呢? 使用ObjectSpace.each_object(IO)无助于了解myios流是否被垃圾收集器或Ruby执行后关闭。
答案 0 :(得分:5)
您可以在文件对象上调用IO#closed?:
f = File.open('stuff.txt', 'w')
p f.closed? # => false
f.close
p f.closed? # => true
请记住,除非你坚持使用你的文件变量,否则Ruby的垃圾收集器最终会找到该文件并将其关闭。但是,我认为最好的做法是尽快关闭文件。
答案 1 :(得分:1)
合理(=全部)操作系统在程序结束时自动关闭fds,无论代码是什么。
对于在执行期间试图变得更好的ruby代码,Ruby具有终结器,当用于引用filedescriptor(或封装的filedescriptor)的变量被垃圾收集时,它会自动关闭。
在UNIX系统上,您可以使用lsof检查打开的文件。
以下代码演示了概念:
<强> rb.rb 强>:
def func()
fd = IO.sysopen("file.txt", "a")
myios = IO.new(fd)
myios.puts "new line"
end
func
sleep 3 #most likely open here unless the GC managed to run
GC.start #should be closed after this point
sleep 3
现在,如果你用:
调用它$ ruby rb.rb & pid=$!; while kill -0 $pid; do if lsof -p $pid | grep -q file.txt; then echo open; else echo closed; fi; sleep 0.3; done
你可能会得到一个“关闭”(在ruby代码赶上之前),3秒打开然后3秒关闭。
如果您不想依赖终结器(它们将在不确定的时间运行,因为它们依赖于垃圾收集器),那么打开文件的块语法在ruby中非常好 - 块的结尾将在块结束的那一点确定性地关闭文件。
答案 2 :(得分:0)
您可能会自己管理。
您可以使用closed?
类中的IO
方法来测试此状态。你可以阅读它here。
有些方法会自动关闭。如果使用块调用,许多将自动关闭。
作为一种不太优雅的方法,如果无法处理文件,您可以挽救异常。