Ruby:如何检查文件是否仍然打开?

时间:2015-09-05 18:17:26

标签: ruby io

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执行后关闭。

3 个答案:

答案 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

有些方法会自动关闭。如果使用块调用,许多将自动关闭。

作为一种不太优雅的方法,如果无法处理文件,您可以挽救异常。

相关问题