不使用eekp值编写函数
我正在尝试使用 C++ 在文件中的特定位置写入一个条目,
所以基本上我有
ofstream ofs("file.dat", ios::binary | ios::app);
ofs.seekp(220, ios::beg);
ofs.write((char *)&i, sizeof(i));
但无论我做什么,它总是写在文件的末尾。
我想这与 iso::app
有关,因为根据文档,
app (append) Set the stream's position indicator to the end of the stream before each output operation
但是如果我使用 ate 或什么都不使用,它总是会删除文件的内容。
任何帮助都会很棒:)
I'm trying to use C++ to write an entry in a specific place in a file
so basicly I have
ofstream ofs("file.dat", ios::binary | ios::app);
ofs.seekp(220, ios::beg);
ofs.write((char *)&i, sizeof(i));
But no matter what I do it always write at the end of the file.
I suppose this is related to iso::app
because according to the documentation
app (append) Set the stream's position indicator to the end of the stream before each output operation
But if I use ate or nothing it always erases the content of the file.
Any help would be great :)
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
是的,正是
ios::app
导致了这种行为。将其替换为 ios::in | ios::out。编辑:您的问题并不清楚,但您的评论表明您正在尝试在文件中间插入数据,而不是覆盖 文件的一部分。如果确实如此,您几乎必须使用第二个文件。
Yes, it's the
ios::app
that's causing this behaviour. Replace it withios::in | ios::out
.edit: It wasn't clear from your question, but your comments suggest that you're trying to insert data in the middle of the file, rather than overwrite a portion of the file. If that is indeed the case, you pretty much have to use a second file for that.
文件追加模式
如果操作系统(和网络文件系统,如果适用)支持追加模式,则设置追加模式可保证在有多个写入者时写入的数据不会覆盖文件中的现有数据。如果没有附加模式,这是无法做到的,因为不同进程的查找和写入之间存在竞争。是日志文件的重要保障。
在附加模式下,根据定义只能在文件末尾写入。
iostream打开模式
根据[ofstream.cons],
ofstream(s, mode)
调用rdbuf()->open(s, mode|ios_base::out)
。根据[filebuf.members]中的“文件打开模式”表,
filebuf::open
的行为是根据fopen
打开模式定义的:out
表示“w”app
,app|out
表示“a”in|out
表示“r+”in| out|trunc
表示“w+”根据
fopen man
,模式含义:最后,
ate
表示fseek(file,0,SEEK_END)
。所以,如果你想在任意位置打开写入,而不破坏现有数据,你需要 fopen(s,"r+") 或 ofstream (s, ios::in|ios ::输出)。
IOW,在 C/C++ 中,您还需要对文件进行读取访问才能打开它进行写入而不覆盖它!
POSIX 世界
您可能想要使用 POSIX
open
函数,以便直接访问 POSIX open 标志:O_READ
、O_WRITE
、O_CREAT
、O_EXCL
、O_TRUNC
...它们不仅功能强大得多,而且具有独立的正交标志并且行为良好,不像filebuf::open
标志。当然,这个函数不是标准 C++ 的一部分。我相信所有与正常编程相关的系统(不是具有特殊特征的利基市场)都支持
开放
。File append mode
If the OS (and network file system, if applicable) supports append mode, setting append mode guarantees that data written does not overwrite existing data in the file when there are multiple writers. That's something you cannot do without append mode, because of the race between seek and write from different processes. It is an important guarantee for log files.
In append mode, you can only write at end of file by definition.
Iostream open modes
According to [ofstream.cons],
ofstream (s, mode)
callsrdbuf()->open(s, mode|ios_base::out)
.According to the table "File open modes" in [filebuf.members], the behaviour of
filebuf::open
is defined in term offopen
open modes:out
means "w"app
andapp|out
mean "a"in|out
means "r+"in|out|trunc
means "w+"According to
fopen man
, the modes mean:Finally,
ate
meansfseek(file,0,SEEK_END)
.So, if you want to open for writing at arbitrary position, without destroying the existing data, you need
fopen(s,"r+")
orofstream (s, ios::in|ios::out)
.IOW, in C/C++ you also need read access to a file to open it for writing without overwriting it!
POSIX world
You may want to use the POSIX
open
function instead, in order to directly access the POSIX open flags:O_READ
,O_WRITE
,O_CREAT
,O_EXCL
,O_TRUNC
... They are not only much more powerful, but also independent orthogonal flags and well-behaved, unlikefilebuf::open
flags.Of course, this function is not part of standard C++. I believe all systems relevant for normal programming (not niche markets with special characteristics) support
open
.您是否尝试过使用 ios::out 而不是 ios::app ?
编辑:
阅读 @curiousguy 引用的文档后,您似乎需要
ios::in | ios::out
而不仅仅是ios::out
以防止截断。Have you tried using
ios::out
instead ofios::app
?EDIT:
After reading the docs that @curiousguy referenced it looks like you would need
ios::in | ios::out
instead of justios::out
to keep from truncating.