将内容添加到文件的中间...而不读取它直到结束

时间:2013-06-19 17:53:53

标签: linux filesystems windows c

我已经在unix.stackexchange上阅读了有关如何在文件中添加或删除行而无需创建临时文件的各种问题/答案。

https://unix.stackexchange.com/questions/11067/is-there-a-way-to-modify-a-file-in-place?lq=1

看来所有这些答案都需要一个至少读取到文件结尾,如果输入是一个大文件,这可能会非常耗时。有没有解决的办法?我希望文件系统像链表一样实现......所以应该有办法达到所需的“行”,然后只添加东西(链接列表中的节点)。我该怎么做呢?

我这么认为是正确的吗?或者我错过了什么?

Ps:我需要在'C'中完成此操作,并且不能使用任何shell命令。

4 个答案:

答案 0 :(得分:8)

简短的回答是,可以修改文件的内容,但没有,无法删除或添加内容文件的中间。

UNIX文件系统使用指向整个数据块的inode pointer structure来实现。文本文件的每一行都不“知道”它与前一行或下一行的关系,它们在块内简单地相邻。要在这两行之间添加内容,需要将以下所有内容在块内进一步“向下”移动,将一些数据推送到下一个块,这反过来又必须转移到下一个块等。

在C中你可以fopen a file for update并阅读其内容,并覆盖一些内容,但我不相信(甚至在理论上)任何方式在中间插入新数据,或删除数据(除了理论上)用空值覆盖它。

答案 1 :(得分:6)

从Linux 4.1开始,fallocate(2)支持FALLOC_FL_INSERT_RANGE标志,允许用户在文件中间插入给定长度的孔而不重写以下数据。但是,它是相当有限的:必须在文件系统块边界插入孔,并且插入的孔的大小必须是文件系统块大小的倍数。此外,在4.1中,此功能仅受XFS文件系统支持,并在4.2中添加了Ext4支持。

对于所有其他情况,仍然需要重写文件的其余部分,如其他答案所示。

答案 2 :(得分:4)

您可以就地修改文件,例如使用dd

$ echo Hello world, how are you today? > helloworld.txt
$ cat helloworld.txt
Hello world, how are you today?
$ echo -n Earth | dd of=helloworld.txt conv=notrunc bs=1 seek=6
$ cat helloworld.txt
Hello Earth, how are you today?

问题是如果您的更改也会改变长度,那么它将无法正常工作:

$ echo -n Joe | dd of=helloworld.txt conv=notrunc bs=1 seek=6
Hello Joeth, how are you today?
$ echo -n Santa Claus | dd of=helloworld.txt conv=notrunc bs=1 seek=6
Hello Santa Clausare you today?

当您更改长度时,您必须重新写入文件,如果不完全,则从您所做的更改点开始。

在C中,这与dd相同。你打开文件,你寻找,然后你写。

答案 3 :(得分:0)

您可以在读/写模式下打开文件。您读取文件(或使用“搜索”跳转到您想要的位置,如果您知道它),然后写入文件,但您覆盖此处的数据(这不是插入)。 然后,您可以选择从您编写的最后一个点截断文件,或者在您编写的点之后保留所有剩余数据而不读取它们。