# IO

- File を open したままにしておくようなコーディングは、C言語レベルでの誤動作*1の原因となるため、あまり好ましくありません。きちんと明示的に close することが大切です。*2

      while
        str = File.open(name).read
      end

  で close を GC 任せにしたりせず、

      while
        begin
          f = File.open(name)
          str = f.read
        ensure
          f.close
        end
      end

  というように ensure 節を使ったり、もしくは

      str = nil
      while
        File.open(name) { |f| str = f.read }
      end

  というように、close が保証されるようにしておいたほうが無難でしょう。*3

- IO からの読み出しは毎回新たなオブジェクトを生成します。ふつうは平気 ですが、意識していないとはた迷惑なプログラムが出来上がる場合があります。

  400byte ほどのブロック二つを連結したものが別のバイナリファイルに入 ているかを調べるプログラムを作った時のこと。総ブロック数 400 個ほど を調べるのにスクリプトの中でループしてたら、たまにシステム全体が一分 程固まったりして。メモリ足りないとはいえ、これは良くない。

  必要に応じて[ruby-list:23467]みたいなものを作る方が良いでしょう。 もっと良いのはこんなことに ruby を使わないことかもしれないけど。 *4

- IO.readはファイルを開くときにバイナリモードにしないので、 バイナリモードの存在する環境でバイナリファイルの読み込みに使うと 内容が壊れることがあります。

*1 stdio でファイルディスクリプタを char で持ってる。そのため、どんどんファイル開いていくと、そのうちファイルディスクリプタが負になってEBADF。(Ruby 1.9 では stdio をあまり使わなくなったため、この制約は緩和されています。[ruby-dev:25128])
*2 ただし、EBADF でなく、EMFILE もしくは ENFILE になった場合には GC が動作し、不要なファイルは close されます。
*3 version 1.7 以降なら str = IO.read(name) とかでもok
*4 version 1.7 以降なら read(400,buf) で ok

links: [IO] [ruby 1.7 feature]
reverse links: [IO] [Rubyの落とし穴] [trap::File]