Reading and writing to the same file using the same fstream(使用相同的 fstream 读取和写入相同的文件)
问题描述
我有一个已经包含一些数据的文件(比如 8 kB).我想从文件的开头读取一些内容,然后从我读完的地方开始覆盖数据.所以我尝试使用以下代码:
I have a file that already contains some data (say, 8 kB). I want to read something from the beginning of the file, and then overwrite data starting where I finished reading. So I try to use the following code:
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
并且实际上没有写入任何内容.
If I execute this code, the first bad()
returns false
, but the second one returns true
and nothing actually gets written.
如果我将 bytesCount
减小到小于 4096(大概是某个内部缓冲区的大小),则第二个 bad()
返回 false
,但仍然没有写入.
If I decrease bytesCount
to anything smaller than 4096 (presumably the size of some internal buffer), the second bad()
returns false
, but still nothing gets written.
如果我取消对 seekp()
行的注释,写入开始工作:bad()
返回 false
并且字节实际被写入.
If I uncomment the seekp()
line, the writing starts working: bad()
returns false
and the bytes actually get written.
为什么这里需要 seekp()
?为什么没有它就不能工作?seekp()
是正确的方法吗?
Why is the seekp()
necessary here? Why doesn't it work without it? Is the seekp()
the right way to do this?
我在 Windows 7 上使用 Visual Studio 2012.
I'm using Visual Studio 2012 on Windows 7.
推荐答案
您违反了 read 和对以 MS fstream
的更新模式打开的文件进行写操作库继承自其 C
实现.
You are falling foul of a restriction upon the intermixing of read and
write operations on a file opened in update mode that MS's fstream
library inherits from from the its C <stdio.h>
implementation.
C 标准(我引用了 C99,但在这一点上它与 C89 没有区别)在 7.19.5.3/6 状态:
The C Standard (I cite C99, but it doesn't differ in this point from C89) at 7.19.5.3/6 states:
当文件以更新模式打开时('+' 作为第二个或第三个字符上面的模式参数值列表),输入和输出都可以在关联流.但是,输出不应直接跟随输入而没有对 fflush 函数或文件定位函数(fseek、fsetpos 或 rewind),并且 input 不能直接跟在没有对文件定位函数的干预调用,除非输入操作遇到结束-文件.
When a file is opened with update mode ('+' as the second or third character in the above list of mode argument values), both input and output may be performed on the associated stream. However, output shall not be directly followed by input without an intervening call to the fflush function or to a file positioning function (fseek, fsetpos, or rewind), and input shall not be directly followed by output without an intervening call to a file positioning function, unless the input operation encounters end- of-file.
(我的重点).
所以你的 stream.seekp(1)
解决方案,它转化为 C fseek
,是正确的.
So your stream.seekp(1)
solution, which devolves to a C fseek
, is correct.
GNU C 库没有此标准限制,因此您发布的代码有效使用 GCC 构建时符合预期.
The GNU C library does not have this Standard limitation, so your code as posted works as expected when built with GCC.
MS
库在继承方面符合 C++ 标准这个限制.fstream
使用 basic_filebuf
实现.在 (C++11) 标准对此模板的说明中,在第 27.9.1.1/2 节,它只是说:
The MS <fstream>
library is compliant with the C++ Standard in inheriting
this restriction. fstream
s are implemented using basic_filebuf<charT,traits>
. In the (C++11) Standard's account of this template, at § 27.9.1.1/2, it simply says:
对由 basic_filebuf 类的对象控制的序列的读写限制与使用标准 C 库文件的读写相同.
The restrictions on reading and writing a sequence controlled by an object of class basic_filebuf are the same as for reading and writing with the Standard C library FILEs.
这篇关于使用相同的 fstream 读取和写入相同的文件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!
本文标题为:使用相同的 fstream 读取和写入相同的文件
基础教程推荐
- 如何使图像调整大小以在 Qt 中缩放? 2021-01-01
- Windows Media Foundation 录制音频 2021-01-01
- 从 std::cin 读取密码 2021-01-01
- 使用从字符串中提取的参数调用函数 2022-01-01
- 如何“在 Finder 中显示"或“在资源管理器中显 2021-01-01
- 如何在不破坏 vtbl 的情况下做相当于 memset(this, ...) 的操作? 2022-01-01
- 管理共享内存应该分配多少内存?(助推) 2022-12-07
- 为 C/C++ 中的项目的 makefile 生成依赖项 2022-01-01
- 在 C++ 中循环遍历所有 Lua 全局变量 2021-01-01
- 为什么语句不能出现在命名空间范围内? 2021-01-01