1

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

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

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

4

2 回答 2

6

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

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

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

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

于 2013-03-01T09:44:06.400 回答
4

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

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

编辑:fflush()记得在截断文件之前打电话!

于 2013-03-01T09:23:03.627 回答