【问题标题】:Reading and writing to the same file using the same fstream使用同一个 fstream 读写同一个文件
【发布时间】:2013-07-06 08:55:15
【问题描述】:

我有一个已经包含一些数据的文件(比如 8 kB)。我想从文件的开头读取一些东西,然后从我读完的地方开始覆盖数据。所以我尝试使用以下代码:

std::fstream stream("filename", std::ios::in | std::ios::out | std::ios::binary);

char byte;
stream.read(&byte, 1);

// stream.seekp(1);

int bytesCount = 4096;

auto bytesVec = std::vector<char>(bytesCount, 'c');
char* bytes = bytesVec.data();

std::cout << stream.bad() << std::endl;

stream.write(bytes, bytesCount);

std::cout << stream.bad() << std::endl;

如果我执行这段代码,第一个bad() 返回false,但第二个返回true,实际上没有写入任何内容。

如果我将 bytesCount 减小到小于 4096 的任何值(可能是某个内部缓冲区的大小),第二个 bad() 将返回 false,但仍然没有写入任何内容。

如果我取消注释 seekp() 行,写入开始工作:bad() 返回 false 并且字节实际被写入。

为什么这里需要seekp()?为什么没有它就行不通? seekp() 是正确的方法吗?

我在 Windows 7 上使用 Visual Studio 2012。

【问题讨论】:

    标签: c++ visual-studio-2012 iostream fstream


    【解决方案1】:

    您违反了对 read 和 对 MS 的 fstream 以更新模式打开的文件进行写入操作 库继承自其 C &lt;stdio.h&gt; 实现。

    C 标准(我引用 C99,但在这一点上它与 C89 没有区别) 在 7.19.5.3/6 状态:

    当以更新模式打开文件时('+' 作为第二个或第三个字符 以上模式参数值列表),输入和输出都可以在 关联的流。但是,输出不得直接跟在输入后面没有 干预对 fflush 函数或文件定位函数(fseek, fsetpos, 或 rewind),并且 input 后​​面不能直接跟 output 而没有 干预对文件定位函数的调用,除非输入操作遇到 end- 文件。

    (我的重点)。

    因此,您的 stream.seekp(1) 解决方案(该解决方案转为 C fseek)是正确的。

    GNU C 库没有此标准限制,因此您发布的代码可以正常工作 使用 GCC 构建时符合预期。

    MS&lt;fstream&gt; 库在继承方面符合 C++ 标准 这个限制。 fstreams 使用 basic_filebuf&lt;charT,traits&gt; 实现。在 (C++11) 标准对该模板的说明中,第 27.9.1.1/2 节中,它简单地说:

    basic_filebuf 类对象控制的序列的读写限制与标准 C 库 FILE 的读写限制相同。

    【讨论】:

    • 这也记录在 C++ 流中吗?还是MS实现在这方面没有遵循标准?
    【解决方案2】:

    您可能想查看绑定流 - http://www.cplusplus.com/reference/ios/ios/tie/

    这使得每次读取输入时都会自动刷新输出,我认为这是您想要的行为,尽管它确实需要单独的输入和输出流

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-04-14
      • 2016-05-09
      • 1970-01-01
      • 1970-01-01
      • 2011-03-09
      • 1970-01-01
      相关资源
      最近更新 更多