如何在Erlang中读取文件的内容?

Zub*_*air 13 erlang

我知道你可以这样做:

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.
Run Code Online (Sandbox Code Playgroud)

:是否有一个单行BIF也可以做到这一点?

Hyn*_*dil 29

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.
Run Code Online (Sandbox Code Playgroud)


小智 10

您可以通过两个步骤来利用file:read_file/1binary:split/3完成这项工作:

readlines(FileName) ->
    {ok, Data} = file:read_file(FileName),
    binary:split(Data, [<<"\n">>], [global]).
Run Code Online (Sandbox Code Playgroud)

  • @MatthewDaiter 不,让它崩溃。 (4认同)