как прочитать содержимое файла в Erlang? - PullRequest
13 голосов
/ 19 марта 2010

Я знаю, что вы можете сделать что-то вроде этого:

readlines(FileName) ->
    {ok, Device} = file:open(FileName, [read]),
    get_all_lines(Device, []).

get_all_lines(Device, Accum) ->
    case io:get_line(Device, "") of
        eof  -> file:close(Device), Accum;
        Line -> get_all_lines(Device, Accum ++ [Line])
    end.

: Есть ли BIF с одним вкладышем, который тоже может это сделать?

Ответы [ 2 ]

28 голосов
/ 19 марта 2010

file: read_file / 1 - это то, что вы ищете. Просто для целей обучения Accum ++ [Line] - плохая практика. Проблема в том, что левый аргумент ++ копируется, а правый используется как есть. В своем коде вы будете копировать все большую и большую часть в каждой итерации. Решением является lists:reverse(Line,Accum), и затем возвращается lists:reverse(Accum) в вашей ветви eof (Или [Line|Accum] и lists:append(lists:reverse(Accum)) в eof или используйте двоичный файл, который имеет лучшую операцию добавления или ...) Другой способ - не использовать хвостовую рекурсивную функцию, которая не так плоха, как кажется в первый раз согласно Миф: Хвостовые рекурсивные функции НАМНОГО быстрее, чем рекурсивные функции

Так что ваша readlines/1 функция должна выглядеть как

readlines(FileName) ->
    {ok, Device} = file:open(FileName, [read]),
    try get_all_lines(Device)
      after file:close(Device)
    end.

get_all_lines(Device) ->
    case io:get_line(Device, "") of
        eof  -> [];
        Line -> Line ++ get_all_lines(Device)
    end.

10 голосов
/ 07 июня 2013

Вы можете использовать file:read_file/1 и binary:split/3 для выполнения этой работы в два этапа:

readlines(FileName) ->
    {ok, Data} = file:read_file(FileName),
    binary:split(Data, [<<"\n">>], [global]).
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...