Wednesday 20 November 2013

Reading Through a File

Leaving behind the idea of reading a file from the standard input... let's open a file and read through it and list it out to the terminal.  We open a file for reading via the function file:open/2.  This module (file) is documented in the Kernel documentation not the Stdlib one.

The first version is like this:

main([Filename]) ->
    {ok, Stream} = file:open(Filename, [read]),
    listout_loop(Stream),
    file:close(Stream).

listout_loop(Stream) ->
    case io:get_line(Stream, "") of
eof ->
            ok;
Line ->
            io:format("~s", [Line]),
            listout_loop(Stream)
    end.

So.  The function file:open takes a file name and a list of options, of which we require just the option to read the file.  It returns an error indication, a possibility which I ignore here, or else a tuple containing the atom ok and a stream which I assign to the identifier Stream.  Then I pass this stream to the function listout_loop, which will be recursive in order to iterate through the file.

In my listout_loop I first call io:get_line, passing the Stream and also an empty string - this latter parameter would be a prompt string if I were getting input from the terminal not a file.  This get_line function now returns possibly an error which again I ignore or else more interestingly either the atom eof or a line of input text which here I assign to the identifier Line.

The construction with the case...of...end statement branches according to the results of the first expression.

If the return value is the atom eof then the function can exit, returning for form's sake the atom ok. Otherwise we print out our Line and the re-call the function to process another.

When the looper function returns of course we close the file.  Job done.

C:\Users\polly\Erlang>escript listout.erl hello.erl

main([]) ->
    io:format("Hello World");
main([Arg]) ->
    io:format("Hello ~s", [Arg]).

No comments:

Post a Comment