RubyのFile.openのブロックによるリソース管理について
File.openのリソース管理について調べてみた。
コードをためす
次のように,いくつかのファイルをそれぞれ異なった書き方で開いてみる:
f1 = f2 = f3 = f4 = f5 = '' #open 1 File.open('test.txt'){|f1| puts f1.read #open 2 f2 = File.open('test2.txt') puts f2.read #open 3 f3 = File.open('test3.txt').each do |l| puts l end #open 4 (f4 = File.open('test4.txt').each do |l| puts l end).close #open 5 File.open('test5.txt'){|f5| f5.read }.each{|l| puts l } } p f1 #=> #<File:test.txt (closed)> p f2 #=> #<File:test2.txt> p f3 #=> #<File:test3.txt> p f4 #=> #<File:test4.txt (closed)> p f5 #=> #<File:test5.txt (closed)>
一番目のファイル test.txt
close される。
これは一番忠実な書き方で,閉じているのは明白かな。
二番目のファイル test2.txt
close されない。
一番目のファイルを開いた File.open のブロックの中で開いたけど,これは閉じてくれない。
三番目のファイル test3.txt
close されない。
一見 close されるように見えるんだけど,each にブロックを渡していて Fire.open にはブロックを渡していないので閉じてくれない。
四番目のファイル test4.txt
close される。
each は self(つまりファイルオブジェクト)を返すから end の後に close を書けば,手動でファイルを閉じたことになる。
五番目のファイル test5.txt
close される。
メソッドチェーンしてみた。一番目と同様,Fire.open にブロックを渡しているので閉じる。Fire.open はブロックを渡されるとブロックの最後の値を返すようだから,こんな書き方ができる。
まとめ
つまり,File.openが自動でリソースを管理してくれるのは,File.open にブロックを渡したときだけみたい。
というかリファレンスにそう書いてあった:
解る人にはこれで十分だろうけど,解らない人が見たらこれじゃ解らないよ^^;open()
はブロックを指定することができます。
ブロックを指定して呼び出した場合は、ファイルオブジェクトを
与えられてブロックが実行されます。ブロックの実行が終了すると、
ファイルは自動的にクローズされます。