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

Pin*_*oyd 1 c++ binary resize file

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

fseek(file,-size(sring.size()),SEEK_END);
Run Code Online (Sandbox Code Playgroud)

然后我该怎么办?我找到了Delete End of File链接,但我不知道该使用哪一个...重新调整文件大小后,我可以简单地使用 编写我的新字符串fwrite吗?

Jam*_*nze 6

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

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

  • 通常在较低级别有系统特定的功能来截断文件。在 Unix 下,这是ftruncate. 但是您需要先找到要截断的字节数;ftruncate需要一个打开的文件,但它不会在文件中的当前位置截断。因此,您必须 1) 在文件中找到最后一行的开头,2) 寻找它,3) 写入新值,4) 调用ftell(或者ftello,如果长度太大而无法容纳long)找到新的结束位置。此时,您遇到了FILE*与较低级别同步的问题 ;就个人而言,我fclose打开了文件,然后用 重新打开它open,并ftruncate从这个打开的文件描述符上执行。(实际上,就个人而言,我会使用open,完成整个工作readlseekwriteftruncateclose。也许可以预先stat找出文件长度。如果您不必翻译双打,那真的没有什么可FILE*添加的。

作为一般规则,我会采用第一种解决方案,只有在结果太慢时才尝试第二种解决方案。(例如,如果文件包含数十亿个双精度数,则复制它们将需要一些时间。)


aaa*_*789 5

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

至于文件大小减小后追加新数据(新字符串),只需查找末尾 ( fseek(file, 0, SEEK_END)) 并fwrite()在那里执行即可。

编辑:fflush()记住在截断文件之前调用!