截断或调整文件大小以修改其结尾
Truncate or resize a file in order to modify its end
我有一个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
,ftruncate
和close
。也许用stat
来查找文件长度前面。如果你不需要翻译双数,FILE*
真的没有添加什么
作为一般规则,我会选择第一个解决方案,并且只尝试第二,如果它太慢了。(如果文件包含几十亿双精度,例如,复制它们)
如果您想调整文件大小,那么ftruncate()
(http://www.linuxmanpages.com/man2/ftruncate.2.php)就是您要查找的函数。但是,您需要在FILE *
结构上调用fileno()
来获取ftruncate()
的文件描述符。
至于在文件缩小后追加新数据(新字符串),只需查找到末尾(fseek(file, 0, SEEK_END)
)和fwrite()
'ing就可以了。
EDIT:记得在截断文件之前调用fflush()
!