问题
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 :)
回答1:
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.
回答2:
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
andapp|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
.
回答3:
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.
来源:https://stackoverflow.com/questions/7928648/write-function-not-using-the-seekp-value