How do I read in lines from a text file in OCaml?
An imperative solution using just the standard library:
let read_file filename =
let lines = ref [] in
let chan = open_in filename in
try
while true; do
lines := input_line chan :: !lines
done; !lines
with End_of_file ->
close_in chan;
List.rev !lines ;;
If you have the Batteries-included library you could read a file into an Enum.t and iterate over it as follows:
let filelines = File.lines_of filename in
Enum.iter ( fun line -> (*Do something with line here*) ) filelines
Here is a simple recursive solution that does not accumulate the lines or use external libraries, but lets you read a line, process it using a function, read the next recursively until done, then exit cleanly. The exit function closes the open filehandle and signals success to the calling program.
let read_lines file process =
let in_ch = open_in file in
let rec read_line () =
let line = try input_line in_ch with End_of_file -> exit 0
in (* process line in this block, then read the next line *)
process line;
read_line ();
in read_line ();;
read_lines some_file print_endline;;
If you have the OCaml Core library installed, then it is as simple as:
open Core.Std
let r file = In_channel.read_lines file
If you have corebuild
installed, then you can just compile your code with it:
corebuild filename.byte
if your code resides in a file named filename.ml
.
If you don't have the OCaml Core, or do not want to install it, or some other standard library implementation, then, of course, you can implement it using a vanilla OCaml's standard library. There is a function input_line
, defined in the Pervasives
module, that is automatically opened in all OCaml programs (i.e. all its definitions are accessible without further clarification with a module name). This function accepts a value of type in_channel
and returns a line, that was read from the channel. Using this function you can implement the required function:
let read_lines name : string list =
let ic = open_in name in
let try_read () =
try Some (input_line ic) with End_of_file -> None in
let rec loop acc = match try_read () with
| Some s -> loop (s :: acc)
| None -> close_in ic; List.rev acc in
loop []
This implementation uses recursion, and is much more natural to OCaml programming.