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

Reading and writing to the same file using the same fstream(使用相同的 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. fstreams 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 读取和写入相同的文件

基础教程推荐