在C语言中删除文件中的一行

17

我想根据特定字符串匹配的条件,删除文件中的某些行,并将指定的行插入同一文件。是否有不使用临时文件复制内容等方式来实现这一点的方法?

3个回答

29
问题在于,一个文件实质上是磁盘(或任何其他物理基质,但无论如何都是)字节数组,而“一行”可以占用不同数量的字节;因此,插入或删除行(除非您总是严格地将一行替换为字节长度完全相同的另一行)需要通过差异字节数“向上”或“向下”“移动”其余文件... 这可能是一项极具负担的操作(即使您只是将文件开头的一行的长度改变1个字节,其余文件也可能是千兆字节级别)。
因此,这样的操作可能极其繁重,因此通常不会作为支持变长行文件的任何语言(C、Python、Java、C++、Ruby或任何其他此类语言)中的基本操作。如果在文件中添加或删除一行,您很有可能真正需要支付这样潜在的性能和风险成本(在数据向上或向下的“移位”期间,系统或磁盘崩溃可能会破坏您整个庞大文件的可用性),而您试图避免使用的完美简单、合适、快速、安全且合理的技术基本上没有任何缺点(因此显然你为什么要避免它?)。
当完成后,使用与源文件不同的结果文件,然后将结果文件mv到源文件上(如果在同一文件系统中,则对大多数系统来说这是一个原子操作),您真的拥有所有可能的最佳选择。

3
你不能轻松地在原地“剪切”文件的部分。你总是需要在其他地方制作一个临时副本。这不是 C 语言的特性,而是任何语言都是如此。
你可以mmap文件,然后当你找到要删除的行时,你可以将其后面的所有内容复制到该行的起始位置。我会质疑这是否高效;临时文件可能更快。

临时文件更加安全 - RBerteig
虽然这不是我的首选...实际上也不是任何选择。这只是我能想到的唯一可能满足请求的方法。这种方法可以说更安全(没有临时文件权限问题),但我同意如果出现某些故障,它会破坏文件。 - Chris Arguin

1
如果文件太大无法在RAM上处理,则可以使用字符串的链表,其中每个节点表示一行,即基于'\n'字符创建链表的节点,然后您可以根据需要对链表执行插入操作和删除操作,然后可以使用链表覆盖同一文件。
例如,mytext.txt
现在,当您创建上述文件的链接列表时,它将如下所示:
插入操作将更改链接列表为:
删除操作将更改链接列表为:

[这是一个测试文件] -> [这是一个新行] -> [必须在上面添加一行] -> [NULL]

现在您可以将链表写入mytext.txt文件,每个节点结尾加上'\n'字符。

最终的文件应该是mytext.txt

这是一个测试文件

这是一个新行

必须在上面添加一行


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接