【问题标题】:Why is fseek or fflush always required between reading and writing in the update modes?为什么在更新模式的读写之间总是需要 fseek 或 fflush?
【发布时间】:2009-11-11 08:29:57
【问题描述】:

问:我正在尝试更新一个文件 放置,通过使用fopen 模式"r+", 读取某个字符串,然后写入 返回一个修改过的字符串,但它不是 工作。

A: 一定要先致电fseek 你写,既要寻回 您正在尝试的字符串的开头 覆盖,并且因为fseekfflush 之间始终需要 读写中的读/写 “+”模式。

我的问题是为什么fseekfflush 在读/写“+”模式下的读和写之间总是需要?第 5.2 节 安德鲁·科尼格 C Traps and Pitfalls (1989) 提到这是因为向后兼容性问题。谁能详细解释一下?

【问题讨论】:

  • “c 陷阱和陷阱”已经超过 20 年了 - 你真的需要向后兼容 20 年前的东西吗?
  • 即使这本书已有 20 年历史,这些规则仍然有效。
  • 注:此要求的C标准相关章节为C11 7.21.5.3/7

标签: c file-io fseek


【解决方案1】:

buffers输入输出操作。查看setvbuf() 和该功能的_IOFBF_IOLBF 参数。

fseek()fflush() 要求库提交缓冲操作。

该标准将查找或刷新操作指定为强制性的,以允许库使用一些快捷方式;否则,对于每个 I/O 操作,lib 必须检查前一个操作是否也是读取操作(或写入操作),如果 I/O 的“方向”发生变化,则自行触发刷新。使用原样的规范,库可能会假设客户端在更改 I/O 方向之前进行了查找/刷新。

【讨论】:

    【解决方案2】:

    因为它使操作系统/库代码更简单。一个文件流可能有单独的 readwrite 缓冲区,并且需要额外的努力来确保它们总是同步的。这在不需要时会降低性能。

    因此,程序员需要在需要时明确地执行此操作。

    【讨论】:

      【解决方案3】:

      阅读 Plauger 的“The Standard C Library”,了解 (C89) 标准库的各种特性为何如此 - 尤其是标准 I/O 库的某些部分为何如此。一个原因是 C 运行在非常多样化的系统和不同的媒体上。磁带等设备的处理方式可能与您习惯认为的磁盘驱动器有所不同。此外,在 Unix 上,考虑您的“tty”设备——它将键盘和鼠标连接到屏幕——三种完全不同的硬件。这些之间的协调已经够棘手了。标准中的规则使它更容易。


      请注意,标准规定了这一点。这是来自 C11 标准 ISO/IEC 9899:2011,但之前的版本中的措辞相似:

      §7.21.5.3 The fopen function

      ¶7 当文件以更新模式打开时('+' 作为第二个或第三个字符 以上模式参数值列表),输入和输出都可以在 关联的流。但是,输出不得直接跟在输入后面没有 干预对fflush 函数或文件定位函数的调用 (fseek, fsetpos, or rewind), 输入后面不能直接跟输出 干预对文件定位函数的调用,除非输入操作遇到文件结尾。使用更新模式打开(或创建)文本文件可能会打开(或创建)一个 一些实现中的二进制流。

      【讨论】:

      • @JonathanLeffler 如果我打算写入现有文件的前半部分,然后立即读取剩余的旧数据,因为我需要在读取和写入模式,我是否需要使用fseek(pFile,0,SEEK_CUR) 来确保缓冲区由于fseek() 设置文件指针位置保持不变而被刷新?我已经提出了一个问题,但没有答案!!
      • @JonathanLeffler 此外,在参考文献中还提到,如果reading operation which did not reach the end-of-file.Indirectly,这是否意味着读取到达文件末尾并且我们想从写入为此,我们不需要刷新缓冲区?
      • @Thokchom:四年后——抱歉耽搁了:标准规定,如果您阅读并遇到 EOF,那么您可以立即写入而无需查找操作。请参阅我的回答中的引用。
      猜你喜欢
      • 2017-07-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-09-24
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多