Erlang Central

Count Lines in a File

Revision as of 13:40, 24 September 2006 by Ayrnieu (Talk | contribs)

Problem

You need to count how many lines are in a file.

Solution

int_countlines(Device, Result) ->
    case io:get_line(Device, "") of
        eof  -> file:close(Device), Result;
        Line -> int_countlines(Device, Result + 1)
    end.
    
countlines(FileName) ->
    {ok, Device} = file:open(FileName,[read]),
    int_countlines(Device, 0).

Which yields the following, when applied to the test file "cookbook.erl":

1> countlines("cookbook.erl").
82

But doesn't this look strikingly like Read_File_to_List?

Discussion

There seems to be a pattern here: open a text file, do something with each line, return the result. Let's define fold-file-lines to abstract this pattern:

int_fold_lines(Device, Kons, Result) ->
    case io:get_line(Device, "") of
        eof  -> file:close(Device), Result;
   Line -> NewResult = Kons(Line, Result),
                int_fold_lines(Device, Kons, NewResult)
    end.

fold_file_lines(FileName, Kons, Knil) ->
    {ok, Device} = file:open(FileName,[read]),
    int_fold_lines(Device, Kons, Knil).

Now we can redefine countlines and readlines like so:

countlines(FileName) ->
  fold_file_lines(FileName, fun(_L,R) -> R + 1 end, 0).

readlines(FileName) ->
    lists:reverse(fold_file_lines(FileName, fun(L,R) -> [L|R] end, [])).