Write function not using the seekp value

2020-03-24 04:14发布

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 :)

3条回答
够拽才男人
2楼-- · 2020-03-24 04:48

Yes, it's the ios::app that's causing this behaviour. Replace it with ios::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.

查看更多
一纸荒年 Trace。
3楼-- · 2020-03-24 04:48

Have you tried using ios::out instead of ios::app?

EDIT:

After reading the docs that @curiousguy referenced it looks like you would need ios::in | ios::out instead of just ios::out to keep from truncating.

查看更多
该账号已被封号
4楼-- · 2020-03-24 04:49

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) calls rdbuf()->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 of fopen open modes:

  • out means "w"
  • app and app|out mean "a"
  • in|out means "r+"
  • in|out|trunc means "w+"

According to fopen man, the modes mean:

  • r+ Open for reading and writing.
  • w Truncate file to zero length or create text file for writing.
  • w+ Open for reading and writing. The file is created if it does not exist, otherwise it is truncated.
  • a Open for appending (writing at end of file). The file is created if it does not exist.

Finally, ate means fseek(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+") or ofstream (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, unlike filebuf::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.

查看更多
登录 后发表回答