LoginSignup
1
0

More than 5 years have passed since last update.

【実際に動かしてみた】RubyのFile.openのブロックによるリソース管理について

Last updated at Posted at 2018-01-31

はじめに

Ruby初学者のため、File.open()の挙動が知りたくなるシチュエーションに遭遇。

調べたら2009年の記事を発見。こちらの記事でFileOpenの動作確認をしていたので、コードを自分でも実際に動かしてみた。パターン網羅的で参考にしやすい。

RubyのFile.openのブロックによるリソース管理について - OSのようなもの -
http://d.hatena.ne.jp/wocota/20090426/1240750685

使わせてもらうコードはこちら

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)>

実行失敗

メソッドチェーンしてる5番目のファイルで実行エラー。

$ ruby file_open.rb
test1です
test2です
test3です
test4です
f.rb:17:in `block in <main>': undefined method `each' for "test5です\n":String (NoMethodError)
    from f.rb:3:in `open'
    from f.rb:3:in `<main>'

修正と再実行

Ruby 1.9 Ruby 1.9では、each_lineメソッドの別名eachが廃止されました。

Stringオブジェクトに対するeachメソッドは廃止されているため、each_lineあたりで代替して動かす。

  • 修正後ソース(抜粋)
  File.open('test5.txt'){|f5|
    f5.read
  }.each_line{|l|
    puts l
  }
  • 再実行結果(抜粋)
""
#<File:test2.txt>
#<File:test3.txt>
#<File:test4.txt (closed)>
""

Rubyのバージョン違いのせいか、f1f5の結果が 参照元 と一致しない。

仮に参照元と同じ動作をするならば、期待としてはファイルオブジェクトが返ってきてほしい。

ブロック内のf1f5は変数のスコープ的にグローバル変数とは別物として扱われ、ファイルオブジェクト(File)は返ってこない。そのため表示されているf1f5は初期化時の空文字(String)が表示される。

結果

参照元のコードだとブロックを使ったときのファイルクローズが目視できなかった。
ただ、.readを使っていることからFile.open('test.txt'){ |f5| f5.read }の戻り値はStringであり、ブロック処理終了後にファイル操作が完結していることが伺える。

Rubyバージョン

2.3.12.4.1で実行

$ ruby -v
ruby 2.3.1p112 (2016-04-26 revision 54768) [x86_64-darwin16]

$ ruby -v
ruby 2.4.1p111 (2017-03-22 revision 58053) [x86_64-darwin16]

参考文献

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0