ファイル操作

これは標準ライブラリが提供するものだけを用いた、 OCaml の基本的なファイル操作のガイドだ。

興味のあるモジュールの公式ドキュメントはこちら: Pervasives, Printf.

標準ライブラリは、読み込んだファイルを直接文字列に入れたり、 直接文字列をファイルに保存したりするような存在しない。 このような関数は Extlib など、サードパーティ製のライブラリにある。 Std.input_file and Std.output_file を見よ。

バッファリングされたチャネル

OCaml で普通にファイルを開くとチャネルを返す。 二種類のチャネルがある。

書き込み

ファイルに書き込むにはこうする:

  1. out_channel を得るためにファイルを開く
  2. チャネルに何か書く
  3. 物理デバイスに書き込みを強制したければ、チャネルをフラッシュしなければならない。そうしないのならすぐに書き込まないだろう。
  4. 終わったらチャネルを閉じる。この時自動的にチャネルはフラッシュされる。

よく使う関数: open_out, open_out_bin, flush, close_out, close_out_noerr

out_channels の標準出力/標準エラー出力版: stdout, stderr

読み込み

ファイルから読み込むにはこうする:

  1. in_channel を得るためにファイルを開く
  2. チャネルから文字を読み込む。読み込みによってチャネルは消費されるので、文字を読み込んだら、チャネルはファイルの次の文字を指すだろう。
  3. 読み込める文字がなくなったときは End_of_File 例外が上がる。そうしたら大抵はチャネルを閉じる。

よく使う関数: open_in, open_in_bin, close_in, close_in_noerr

in_channel の標準入力版: stdin

シーク

何かをチャネルから読み込んだりチャネルに書き込んだりするときはいつも、 読み書きの直後に現在位置が次の文字に移動する。 ファイルの特定の位置に移動したいようなときや、 ファイルを最初から読み直したいときもあるだろう。 普通のファイルの位置を変えることは出来る。 seek_inseek_out が使える。

これで大丈夫

open Printf

let file = "example.dat"
let message = "Hello!"

let _ =

  (* message をファイルに書く *)
  let oc = open_out file in    (* ファイルの新規作成か切捨て。チャネルが返る *)
  fprintf oc "%s\n" message;   (* 何か書く *)   
  close_out oc;                (* チャネルをフラッシュして閉じる *)

  (* ファイルから読んで最初の行を表示 *)
  let ic = open_in file in
  try 
    let line = input_line ic in  (* in_channel から1行読んで捨てる \n *)
    print_endline line;          (* 結果を stdout に書く *)
    flush stdout;                (* ここで実際に対象デバイスに書き込む *)
    close_in ic                  (* 入力チャネルを閉じる *) 

  with e ->                      (* 期待しない例外が起こったとき *)
    close_in_noerr ic;           (* 緊急にチャネルを閉じる *)
    raise e                      (* エラー終了: ファイルは閉じられるが
                                    チャネルはフラッシュされない *)

  (* 通常終了: チャネルは全てフラッシュされて閉じられる *)