截断或调整文件大小以修改其结尾

Truncate or resize a file in order to modify its end

本文关键字:修改 结尾 文件大小 调整      更新时间:2023-10-16

我有一个FILE* file保存一些二进制数据。假设这个数据是一个双精度体列表,最后一项是一个字符串,描述了这些双精度体是什么。我想修改这个字符串(新字符串可能更短)。所以首先我删除旧的字符串。我需要找到字符串的起始点:

fseek(file,-size(sring.size()),SEEK_END);

然后我该怎么做?我找到了删除文件结束链接,但我不知道该用哪个…一旦文件大小调整,我可以简单地用fwrite写我的新字符串吗?

FILE*和iostream都不支持截断。如果你想编辑文件,使新文件比旧文件短有两个解决方案:

  • 通常的解决方案是将原始文件复制到新的文件中文件,在运行过程中进行任何更改。完成后,关闭新建文件,确认没有错误(这一点很重要),然后删除原始文件并将其重命名为新文件以具有原来的名字。这可能会在Unix系统上导致问题有原始文件的硬链接。(通常情况下,这这不是问题,因为现在每个人都用软链接。如果是,您应该stat原始的,如果st_nlink字段是大于1,将新文件复制到原始文件上,然后删除新文件。)另一方面,它是最通用的选择;它适用于所有类型的修改,在任何地方文件。

  • 通常在较低的层次有系统特定的功能截断一个文件。在Unix下,这是ftruncate。但您需要找到要截断的字节数第一个;ftruncate需要一个打开的文件,但它不会截断在文件中的当前位置。所以你得自己去找从文件的最后一行开始,2)seek到它,3)write调用ftell(或者ftello,如果长度允许的话)太大了,无法在long上找到新的结束位置。在这一点上,您遇到了同步您的FILE*为低电平;就我个人而言,我会fclose文件,然后用open重新打开它,并在文件上执行ftruncate描述符从此打开。(事实上,就我个人而言,我会做整个作业使用open, read, lseek, write, ftruncateclose。也许用stat来查找文件长度前面。如果你不需要翻译双数,FILE*真的没有添加什么

作为一般规则,我会选择第一个解决方案,并且只尝试第二,如果它太慢了。(如果文件包含几十亿双精度,例如,复制它们)

如果您想调整文件大小,那么ftruncate() (http://www.linuxmanpages.com/man2/ftruncate.2.php)就是您要查找的函数。但是,您需要在FILE *结构上调用fileno()来获取ftruncate()的文件描述符。

至于在文件缩小后追加新数据(新字符串),只需查找到末尾(fseek(file, 0, SEEK_END))和fwrite() 'ing就可以了。

EDIT:记得在截断文件之前调用fflush() !