首页 文章

使用相同的fstream读取和写入同一文件

提问于
浏览
12

我有一个已包含一些数据的文件(例如,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 .

2 回答

  • 1

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

    这使得每次输入读取输出都会自动刷新,这是我认为你想要的行为,虽然它确实需要一个单独的输入和输出流

  • 22

    对于在更新模式下打开的文件(对MS的 fstream 库继承自其C <stdio.h> 实现)的读写操作的混合,您正在违反限制 .

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

    当使用更新模式打开文件时(''作为上述模式参数值列表中的第二个或第三个字符),可以在关联的流上执行输入和输出 . 但是,输入不应直接跟随输入而不干涉fflush功能或文件定位功能(fseek,fsetpos或rewind),并且输入不应直接跟随输出而不干预文件定位函数,除非输入操作遇到文件结尾 .

    (我的重点) .

    所以你的 stream.seekp(1) 解决方案,它转换为C fseek ,是正确的 .

    GNU C库没有此标准限制,因此当使用GCC构建时,您发布的代码按预期工作 .

    MS <fstream> 库在继承此限制时符合C标准 . fstream 是使用 basic_filebuf<charT,traits> 实现的 . 在(C 11)标准对该模板的描述中,在第27.9.1.1/2节中,它只是说:

    读取和编写由basic_filebuf类对象控制的序列的限制与使用Standard C库FILE读取和写入的限制相同 .

相关问题