it-swarm-ja.tech

RubyでFile.open、open、IO.foreachの違いは何ですか?

次のAPIはすべて同じことを行います。ファイルを開き、各行のブロックを呼び出します。どちらを使うべきかという好みはありますか?

File.open("file").each_line {|line| puts line}
open("file").each_line {|line| puts line}   
IO.foreach("file") {|line | puts line}
50
pierrotlefou

これら3つの選択肢の間には重要な違いがあります。

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/
_

2番目のケースでは、_Kernel#open_によって返されるStringIOオブジェクトは、実際には 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 …
_

riは、Rubyのドキュメントを表示するツールです。シェルでこのように使用します。

_ri File.open
ri open
ri IO.foreach
ri File#each_line
_

これを使えば、私がここで書いたほとんどすべての情報を見つけることができます。

82
johannes