web-dev-qa-db-ja.com

RubyのFile.openとf.closeの必要性

ほとんどのプログラミング言語では、ファイルを操作するためのフローがオープンユースとクローズであることは一般的な知識です。それでも、Rubyコードが一致しないFile.open呼び出しで何度も見ました。さらに、 この知識の宝石 をRuby docs:

I/Oストリームは、ガベージコレクターによって要求されると自動的に閉じられます。

darkredandyellowフレンドリーなircが問題を引き受けます:
[17:12]はい、また、ファイル記述子の数は通常OSによって制限されます
[17:29]利用可能なファイル記述子を簡単に使い果たすことができると思いますbeforeガベージコレクターがクリーンアップします。この場合、自分で閉じて使用することもできます。 「ガベージコレクターによって要求されました。」 GCは将来のある時点で機能することを意味します。そしてそれは高価です。ファイルを明示的に閉じる多くの理由。

  1. 明示的に閉じる必要がありますか
  2. はいの場合、GCはなぜ自動クローズしますか?
  3. そうでない場合、なぜオプションですか?
83
clyfe

Ruby一致しないコードFile.open呼び出し

例を挙げていただけますか? lack初心者によって書かれたコードでは、「ファイルを操作するためのフローがオープンユースであるというほとんどのプログラミング言語の常識」閉じる"。

経験豊富なルビイストは、明示的にファイルを閉じるか、より慣用的には、ブロック形式の 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

スクリプトは特別なケースです。通常、スクリプトは非常に短く実行されるため、スクリプトを終了するときにオペレーティングシステムによってスクリプトが閉じられるため、ファイル記述子をほとんど使用しないため、スクリプトを閉じるのは意味がありません。

明示的に閉じる必要がありますか?

はい。

「はい」の場合、GCが自動的に閉じるのはなぜですか?

オブジェクトを収集した後は、ファイルを閉じることができないため、ファイル記述子がリークするためです。

ファイルを閉じるのはガベージコレクターではないことに注意してください。ガベージコレクターは、オブジェクトを収集する前に、オブジェクトのファイナライザーを実行するだけです。 Fileクラスがファイルを閉じるファイナライザーを定義するのはたまたま起こります。

そうでない場合、なぜオプションですか?

無駄なメモリは安価ですが、無駄なファイル記述子はそうではありません。したがって、ファイル記述子のライフタイムをメモリのチャンクのライフタイムに関連付けることは意味がありません。

ガベージコレクターがいつ実行されるかwhenを予測することはできません。予測することさえできませんifそれが実行されますまったく:メモリが不足すると、ガベージコレクターが実行されないため、ファイナライザーが実行されないため、ファイルが閉じられません。

123
Jörg W Mittag

使用後は常にファイル記述子を閉じる必要があります。これにより、ファイル記述子もフラッシュされます。多くの場合、人々は File.open または同等のメソッドとブロックを使用して、ファイル記述子の有効期間を処理します。例えば:

File.open('foo', 'w') do |f|
    f.write "bar"
end

その例では、ファイルは自動的に閉じられます。

67
Tonttu
  1. はい
  2. しない場合、または他の障害がある場合
  3. 2.をご覧ください。
1
Satya

http://Ruby-doc.org/core-2.1.4/File.html#method-c-open

関連するブロックがない場合、File.openは:: newの同義語です。オプションのコードブロックが指定されている場合、開かれたファイルが引数として渡され、ブロックが終了するとFileオブジェクトが自動的に閉じられます。ブロックの値はFile.openから返されます。

したがって、ブロックが終了するとは自動的に閉じられます:D

1
skozz