人気ブログランキング | 話題のタグを見る

System.IO モジュール(6) withFile

System.IO モジュールの関数 withFile :: FilePath -> IOMode -> (Handle -> IO r) -> IO r は、openFile 関数と同じようにファイルをオープンするが、openFile 関数と違って第三引数に Handle を引数とする関数をとることができる。

つまり、withFile 関数は、第1引数で指定したファイルパスを第2引数のモードでオープンし、そのファイルに第3引数の関数を適用して、最後にファイルをクローズする。

次の例ではファイルをオープンして、ファイルサイズを取得し、ファイルをクローズしている。
Prelude System.IO> withFile "hello.txt" ReadMode hFileSize
34

これは、次のプログラムがやっていることと同じだ。
Prelude System.IO> do fhandle <- openFile "hello.txt" ReadMode; size <- hFileSize fhandle; hClose fhandle; return size
34

上のプログラムは、ちょっと面倒だが、do 記法を使わないでも書くことが出来る。
Prelude System.IO> let fhandle = openFile "hello.txt" ReadMode in (let size = (fhandle >>= hFileSize) in (fhandle >>= hClose >> size))
34

hFileSize の代わりに hGetLine を使っても withFile を実行することが出来る。
Prelude System.IO> withFile "hello.txt" ReadMode hGetLine
"hello, world"

しかし、hGetContents では空の文字列しか帰ってこない。
Prelude System.IO> withFile "hello.txt" ReadMode hGetContents
""

これはおそらく仕様だろう。遅延評価の関係ではないだろうか。ファイルの内容全部を取得したいときは、上のプログラムの代わりに、readFile 関数を使う。
Prelude System.IO> readFile "hello.txt"
"hello, world\nnice to meet you\n"

こっちの方が楽だ。


注:
withFile 関数は Prelude には定義されていないので :m コマンドで System.IO モジュールをインポートする必要がある。
Prelude> :t withFile

:1:0: Not in scope: `withFile'
Prelude> :m System.IO
Prelude System.IO> :t withFile
withFile :: FilePath -> IOMode -> (Handle -> IO r) -> IO r
by tnomura9 | 2011-09-11 03:47 | Haskell | Comments(0)
<< System.IO モジュール... YouTube 気になるチャンネル >>