【发布时间】:2011-11-21 16:37:32
【问题描述】:
我们知道调用 fprintf 或 fwrite 等函数不会立即将数据写入磁盘,而是会缓冲数据直到达到阈值。我的问题是,如果我调用 fseek 函数,这些缓冲数据会在寻找新位置之前写入磁盘吗?还是数据还在缓冲区中,正在写入新位置?
程
【问题讨论】:
我们知道调用 fprintf 或 fwrite 等函数不会立即将数据写入磁盘,而是会缓冲数据直到达到阈值。我的问题是,如果我调用 fseek 函数,这些缓冲数据会在寻找新位置之前写入磁盘吗?还是数据还在缓冲区中,正在写入新位置?
程
【问题讨论】:
我不知道缓冲区是否保证被刷新,如果你寻求一个足够接近的位置,它可能不会。但是,缓冲的数据无法写入新位置。缓冲只是一种优化,因此它必须是透明的。
【讨论】:
fseek 会像根本没有缓冲一样工作。
fflush、setbuf 等)
是的; fseek() 确保根据您执行的fwrite() 操作,文件看起来应该是它应该的样子。
C 标准 ISO/IEC 9899:1999 §7.19.9.2 fseek() 说:
fseek 函数为 stream 指向的流设置文件位置指示符。 如果发生读取或写入错误,则会设置流的错误指示器并且 fseek 失败。
【讨论】:
fseek()。
fseek 必须等同于fflush?我不太清楚。
我不认为它指定必须在 fseek 上刷新数据,但是当数据实际写入磁盘时,它必须写入到调用 write 函数时流所在的位置。即使数据仍在缓冲中,该缓冲区在刷新时也无法写入文件的其他部分,即使有后续查找。
【讨论】:
看来您真正关心的是,如果您执行fseek,之前写入(但尚未刷新)的数据是否会最终出现在文件中的错误位置。
不,这不会发生。它会按照您的预期运行。
【讨论】:
我对您之前致电fflush 的要求有模糊记忆
fseek,但我没有可用于验证的 C 标准副本。
(如果你不这样做,那将是未定义的行为或定义的实现,
或类似的东西。)通用 Unix 标准规定:
如果给定流上的最新操作(除 ftell() 之外)是 fflush(),底层打开文件描述中的文件偏移量 应调整以反映 fseek() 指定的位置。
[...]
如果流是可写的并且缓冲的数据没有被写入 底层文件 fseek() 将导致未写入的数据 写入文件并标记 st_ctime 和 st_mtime 字段 要更新的文件。
然而,这被标记为对 ISO C 标准的扩展,因此除了 Unix 平台(或做出类似保证的其他平台)之外,您不能指望它。
【讨论】:
fseek 之前调用fflush,那么提到fseek 将是多余的,因为无论如何都会有刷新。
fflush,但我没有我的标准副本可以方便地验证它的位置(而且由于我通常只使用 C++ I/O,因此我不记得 C 风格的 IO)。