如何使用Erlang OTP模块修改文件中的行

时间:2014-06-10 09:01:00

标签: file-io erlang

我有一个大文件,我想用其他内容替换第一行。 当我使用{ok, IoDev} = file:open("/root/FileName", [write, raw, binary])时,整个内容都会被移除。

但是当我使用{ok, IoDev} = file:open("/root/FileName", [append, raw, binary])file:pwrite(S, {bof,0}, <<"new content\n">>)时,我得到了结果{error, badarg}

如果我将Location设置为0:file:pwrite(S, 0, <<"new content\n">>),则该字符串将附加在文件的尾部。

2 个答案:

答案 0 :(得分:4)

您似乎对实际的文件API感到困惑。

如果您通过[write, raw, binary]

file:open/2将截断文件:

  

(约write模式):打开文件进行写入。如果它不存在,则创建它。如果文件存在,并且write未与read合并,则文件将被截断。

因此,您需要传递[write, read][write, append]

file:pwrite/3也完全符合记录。它允许您在文件中的给定位置写入。特别是,由于您以原始模式打开文件,因此无法将{bof, 0}作为第二个参数传递:

  

如果在原始模式下打开IoDevice,则会有一些限制:Location只允许为整数;操作后,文件的当前位置未定义。

以下示例代码显示了它们的工作原理:

ok = file:write_file("/tmp/file", "This is line 1.\nThis is line 2.\n"),
{ok, F} = file:open("/tmp/file", [read, write, raw, binary]),
ok = file:pwrite(F, 0, <<"This is line A.\n">>),
ok = file:close(F),
{ok, Content} = file:read_file("/tmp/file"),
io:put_chars(Content),
ok = file:delete("/tmp/file").

将输出:

This is line A.
This is line 2.

这是有效的,因为文字"This is line A.\n""This is line 1.\n"完全一样长。它并不真正取代行,而只是字节。如果需要将第一行替换为具有不同长度的内容,则需要重写文件的整个内容。一种常见的方法确实是编写一个新文件并最终交换它们。但是,如果文件足够小,您可以完全在内存中读取它并重写它。 file:read_file/1file:write_file/2可行:

replace_first_line(Path, NewLine) ->
    {ok, Content} = file:read_file(Path),
    [FirstLine | Tail] = binary:split(Content, <<"\n">>),
    NewContent = [NewLine, <<"\n">> | Tail],
    ok = file:write_file(Path, NewContent).

答案 1 :(得分:0)

这个问题与erlang无关,而是与一般文件操作有关。

替换文件中的行需要重写整个文件。最简单的方法是将所有新内容写入新文件,然后移动文件。