在Ruby中使用File.open,open和IO.foreach,有什么区别?

pie*_*fou 53 ruby file-io

所有以下API都做同样的事情:打开一个文件并为每一行调用一个块.有什么偏好我们应该使用一个而不是另一个?

File.open("file").each_line {|line| puts line}
open("file").each_line {|line| puts line}   
IO.foreach("file") {|line | puts line}
Run Code Online (Sandbox Code Playgroud)

joh*_*nes 84

这三种选择之间存在重要差异.

File.open("file").each_line { |line| puts line }

  • File.open 打开本地文件并返回文件对象
  • 文件保持打开状态,直到你打电话IO#close给它

open("file").each_line { |line| puts line }

Kernel.open 查看字符串以决定如何处理它.

open(".irbrc").class # => File
open("http://google.com/").class # => StringIO
File.open("http://google.com/") # => Errno::ENOENT: No such file or directory - http://google.com/
Run Code Online (Sandbox Code Playgroud)

在第二种情况下StringIO,Kernel#open实际返回的对象包含http://google.com/的内容.如果Kernel#open返回一个File对象,它会保持打开状态,直到你调用IO#close它为止.

IO.foreach("file") { |line| puts line }

  • IO.foreach 打开一个文件,为它读取的每一行调用给定的块,然后关闭文件.
  • 您不必担心关闭文件.

File.read("file").each { |line| puts line }

你没有提到这个选择,但这是我在大多数情况下会使用的选择.

  • File.read 完全读取文件并将其作为字符串返回.
  • 您不必担心关闭文件.
  • IO.foreach此相比较清楚地表明,您正在处理文件.
  • 其存储器复杂度为O(n).如果你知道你正在处理一个小文件,这不是缺点.但是,如果它可以是一个大文件,并且您知道您的内存复杂性可能小于O(n),请不要使用此选项.

它在这种情况下失败:

 s= File.read("/dev/zero") # => never terminates
 s.each …
Run Code Online (Sandbox Code Playgroud)

RI

ri是一个向您显示ruby文档的工具.你在shell上使用它就像这样.

ri File.open
ri open
ri IO.foreach
ri File#each_line
Run Code Online (Sandbox Code Playgroud)

有了这个,你几乎可以找到我在这里写的所有东西.

  • 感谢礼貌的"ri"提醒 - 绅士的RTFM. (27认同)
  • File是IO的子类,因此如果要使其更加自我记录,您可以使用File.foreach而不是IO.foreach.请注意,File.read().每个都将整个文件加载到内存中.如果您正在处理大型文件,则可能不建议这样做.我会坚持使用File.foreach. (12认同)
  • 如果将块传递给`File.open`,它将在块终止时自动关闭,无需调用`IO#close` (9认同)