In Ocaml, I/O operations are performed on “channels” that we can think of as files.
There are two types of channels:
type in_channel
can be used to read input into a programtype out_channel
that can be used for output.There are also three “pre-opened channels”:
val stdin : in_channel
(the standard input)val stdout : out_channel
(the standard output)val stderr : out_channel
(for logging/printing errors)The common way to open a channel is by file name:
val open_out : string -> out_channel
takes a filename as input and returns an out_channel
val open_in : string -> in_channel
takes a filename as input and returns an in_channel
These can raise Sys_error
if the file cannot be opened.
Once a program has finished using a channel, it should be closed with:
val close_out : out_channel -> unit
orval close_in : in_channel -> unit
To read from a file, the most common methods are
val input_char : in_channel -> char
- reads a single char
val input_line : in_channel -> string
- reads a line, trims newline.val read_line : unit -> string
(input_line
from stdin)If the channel (file) does not have more data, these raise End_of_file
.
A common pattern is the “stream” approach:
unit -> string option
Some v
End_of_file
is raised, close the channel and return None
let stream_of_file f =
let ic = open_in f in
let nextline () =
begin
try Some (input_line ic) with
End_of_file -> let () = close_in ic in None
end
in nextline
Another approach makes a list of all lines in the file:
Still not quite right:
let get_file_lines f =
let ic = open_in f in
let rec gfl_helper acc =
try gfl_helper ((input_line ic)::acc)
with End_of_file -> (let () = close_in ic in acc)
in List.rev (gfl_helper [])
try
should wrap only the input_line
call:
To write to an out_channel
, the commonly used functions are:
val output_char : out_channel -> char -> unit
val output_string : out_channel -> string -> unit
These can raise Sys_error
if writing fails.
Example: write a string list
to a file, one line at a time:
What about writing a list of int*int
pairs, separated by tabs, followed by newlines?
The Printf
module provides a mechanism for formatted output:
Printf.sprintf
writes formatted input to a stringPrintf.printf
prints formatted input to stdout
Printf.fprintf oc
prints formatted input to oc : out_channel
Printf.printf <fs>
is a function with the correct number of inputs to match the format string <fs>
:
More on conversions in Hickey and the Ocaml manual
Example: write_pair_list
again…
cs2041.org