This is what I have so far. Isn\'t this all that you need? I keep getting the error \"Error: Unbound module Std\"
let r file =
let chan = open_in file in
Here's a recursive solution using Scanf:
let read_all_lines file_name =
let in_channel = open_in file_name in
let rec read_recursive lines =
try
Scanf.fscanf in_channel "%[^\r\n]\n" (fun x -> read_recursive (x :: lines))
with
End_of_file ->
lines in
let lines = read_recursive [] in
let _ = close_in_noerr in_channel in
List.rev (lines);;
Usage:
let all_lines = read_all_lines "input.txt";;
However, I'd prefer to stream line-by-line:
let make_reader file_name =
let in_channel = open_in file_name in
let closed = ref false in
let read_next_line = fun () ->
if !closed then
None
else
try
Some (Scanf.fscanf in_channel "%[^\r\n]\n" (fun x -> x))
with
End_of_file ->
let _ = close_in_noerr in_channel in
let _ = closed := true in
None in
read_next_line;;
Usage:
let read_next = make_reader "input.txt";;
let next_line = read_next ();;
And may be a bit of icing:
type reader = {read_next : unit -> string option};;
let make_reader file_name =
let in_channel = open_in file_name in
let closed = ref false in
let read_next_line = fun () ->
if !closed then
None
else
try
Some (Scanf.fscanf in_channel "%[^\r\n]\n" (fun x -> x))
with
End_of_file ->
let _ = close_in_noerr in_channel in
let _ = closed := true in
None in
{read_next = read_next_line};;
Usage:
let r = make_reader "input.txt";;
let next_line = r.read_next ();;
Hope this helps!
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.
Another style to read lines from a file using Scanf "string indiciation" and zero-width character. It is like traditional imperative style.
open Scanf
open Printf
(* little helper functions *)
let id x = x
let const x = fun _ -> x
let read_line file = fscanf file "%s@\n" id
let is_eof file = try fscanf file "%0c" (const false) with End_of_file -> true
let _ =
let file = open_in "/path/to/file" in
while not (is_eof file) do
let s = read_line file in
(* do something with s *)
printf "%s\n" s
done;
close_in file
NOTE:
This reads the file's lines and prints each of them:
open Core.Std
let handle_line line =
printf "Your line: %s \n" line
let () =
let file_to_read = "./file_to_read.txt" in
let lines = In_channel.read_lines file_to_read in
List.iter ~f: handle_line lines
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
Std.input_list apparently requires Extlib, which you should install on your system (libextlib-ocaml and libextlib-ocaml-dev on Debian systems).