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.

Tags:

Ocaml