Ruby的File.open和对f.close的需求

cly*_*yfe 86 ruby file

在大多数编程语言中,使用文件的流程是开放使用关闭的常识.然而,我在ruby代码中多次看到无法比拟的File.open调用,而且我在ruby文档中发现了这些宝石知识:

当垃圾收集器声明I/O流时,它们会自动关闭.

darkredandyellow friendly irc承担了这个问题:
[17:12]是的,而且,文件描述符的数量通常受操作系统的限制
[17:29]我假设在垃圾收集器清理之前你很容易用完可用的文件描述符起来.在这种情况下,您可能希望自己使用它们."垃圾收集者声称." 意味着GC将来会在某个时刻发挥作用.而且价格昂贵.明确关闭文件的原因很多.

  1. 我们需要明确关闭吗?
  2. 如果是,那么为什么GC会自动关闭?
  3. 如果不是那么为什么选择?

Jör*_*tag 125

我在ruby代码中多次看到无与伦比的File.open通话

你能给我举个例子吗?我只看到在新手编写的代码中,他们缺乏 "大多数编程语言中的常识,使用文件的流程是开放使用 - 关闭".

有经验的Rubyist要么显式关闭他们的文件,要么更惯用,使用块形式File.open,它会自动关闭文件.它的实现基本上看起来像这样:

def File.open(*args, &block)
  return open_with_block(*args, &block) if block_given?
  open_without_block(*args)
end

def File.open_without_block(*args)
  # do whatever ...
end

def File.open_with_block(*args)
  yield f = open_without_block(*args)
ensure
  f.close
end
Run Code Online (Sandbox Code Playgroud)

脚本是一个特例.脚本通常运行得如此之短,并且使用如此少的文件描述符使得关闭它们根本没有意义,因为操作系统无论如何都会在脚本退出时关闭它们.

我们需要明确关闭吗?

是.

如果是,那么为什么GC会自动关闭?

因为在收集了对象之后,您无法再关闭文件,因此会泄漏文件描述符.

请注意,关闭文件的不是垃圾收集器.垃圾收集器在收集对象之前只执行对象的任何终结器.恰好这个File类定义了一个关闭文件的终结器.

如果不是那么为什么选择?

因为浪费的内存很便宜,但浪费的文件描述符则不然.因此,将文件描述符的生命周期与某些内存块的生命周期联系起来是没有意义的.

你根本无法预测,当垃圾收集器将运行.你甚至不能预测,如果它将运行在所有的:如果你从来没有用完的内存,垃圾收集器将永远不会运行,因此终结永远不会运行,因此该文件将永远不会被关闭.

  • 在这个例子中,应该提升到救援区内吗?如果调用raise并且没有异常,这不会抛出运行时错误吗? (3认同)

Ton*_*ttu 68

您应该在使用后关闭文件描述符,这也将刷新它.通常人们使用File.open或带有块的等效方法来处理文件描述符生存期.例如:

File.open('foo', 'w') do |f|
    f.write "bar"
end
Run Code Online (Sandbox Code Playgroud)

在该示例中,文件自动关闭.