我有一个大文件,我想用其他内容替换第一行。
当我使用{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">>)
,则该字符串将附加在文件的尾部。
答案 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/1
和file: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无关,而是与一般文件操作有关。
替换文件中的行需要重写整个文件。最简单的方法是将所有新内容写入新文件,然后移动文件。