如何在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.
是否有一个单衬垫 BIF 也可以做到这一点?
I know you can do something like this:
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.
Is there a one liner BIF that can do this too?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
file:read_file/1 就是您要查找的内容。仅出于教学目的,
Accum ++ [Line]
是不好的做法。问题是++
的左参数被复制,而右参数按原样使用。在您的代码中,您将在每次迭代中复制越来越大的部分。解决方案是lists:reverse(Line,Accum)
,然后在eof
分支中返回lists:reverse(Accum)
(或者[ Line|Accum]
和lists:append(lists:reverse(Accum))
在eof
或使用具有更好附加操作的二进制文件或...) 。另一种方法是不使用尾递归函数,根据 神话,它并不像第一次看起来那么糟糕:尾递归函数比递归函数快得多。所以你的 readlines/1 函数应该看起来像
file:read_file/1 is what you are looking for. Just for teaching purpose,
Accum ++ [Line]
is bad practice. Problem is that left argument of++
is copied and right is used as is. In your code you will copy bigger and bigger part in each iteration. Solution islists:reverse(Line,Accum)
and than returnlists:reverse(Accum)
in youreof
branch (Or[Line|Accum]
andlists:append(lists:reverse(Accum))
at theeof
or use binary which have better append operation or ...). Another way is not using tail recursive function which is not so bad as seems at first time according to Myth: Tail-recursive functions are MUCH faster than recursive functions.So your
readlines/1
function should look like您可以利用
file:read_file/1
和binary:split/3
分两步完成这项工作:You could leverage
file:read_file/1
andbinary:split/3
to do this work in two steps: