Tuesday, April 7, 2009

OCaml file manipulation

The normal way of opening a file in OCaml returns a channel. There are two kinds of channels:

channels that write to a file: type out_channel
channels that read from a file: type in_channel

Writing

For writing into a file, you would do this:
1. Open the file to obtain an out_channel
2. Write stuff to the channel
3. If you want to force writing to the physical device, you must flush the channel, otherwise writing will not take place immediately.
4. When you are done, you can close the channel. This flushes the channel automatically.

Commonly used functions: open_out, open_out_bin, flush, close_out, close_out_noerr
Standard out_channels: stdout, stderr

Reading

For reading data from a file you would do this:
1. Open the file to obtain an in_channel
2. Read characters from the channel. Reading consumes the channel, so if you read a character, the channel will point to the next character in the file.
3. When there are no more characters to read, the End_of_file exception is raised. Often, this is where you want to close the channel.
Commonly used functions: open_in, open_in_bin, close_in, close_in_noerr
Standard in_channel: stdin

Example

open Printf

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

let _ =

(* Write message to file *)
let oc = open_out file in (* create or truncate file, return channel *)
fprintf oc "%s\n" message; (* write something *)
close_out oc; (* flush and close the channel *)

(* Read file and display the first line *)
let ic = open_in file in
try
let line = input_line ic in (* read line from in_channel and discard \n *)
print_endline line; (* write the result to stdout *)
flush stdout; (* write on the underlying device now *)
close_in ic (* close the input channel *)

with e -> (* some unexpected exception occurs *)
close_in_noerr ic; (* emergency closing *)
raise e (* exit with error: files are closed but
channels are not flushed *)

(* normal exit: all channels are flushed and closed *)

1 comment:

Steven Cheng said...

Cool, thanks, just used this.

Took me a while to find out that these functions are in the Pervasives library.