I am trying to open a file for output and append to it. After appending to it, I want to move my output position somewhere else in the file and overwrite existing data. As I understand it, std::ios_base::app
will force all writes to be at the end of the file which is not what I want to do. As such, I believe std::ios_base::ate
is the correct flag to pass to std::ofstream::open()
. However, it seems to be not working as expected:
// g++ test.cpp
// clang++ test.cpp
// with and without -std=c++11
#include <iostream>
#include <fstream>
int main() {
std::streampos fin, at;
{
std::ofstream initial;
initial.open("test", std::ios_base::out | std::ios_base::binary);
if ( not initial.good() ) {
std::cerr << "initial bad open" << std::endl;
return 1;
}
int b = 100;
initial.write((char*)&b, sizeof(b));
initial.flush();
if ( not initial.good() ) {
std::cerr << "initial write bad" << std::endl;
return 1;
}
fin = initial.tellp();
}
{
std::ofstream check;
check.open("test", std::ios_base::out | std::ios_base::binary | std::ios_base::ate);
if ( not check.good() ) {
std::cerr << "check bad open" << std::endl;
return 1;
}
at = check.tellp();
if ( fin != at ) {
std::cerr << "opened at wrong position!
fin:" << fin << "
" << "at:" << at << std::endl;
return 1;
}
int bb = 200;
check.write((char*)&bb, sizeof(bb));
check.flush();
if ( not check.good() ) {
std::cerr << "check write bad" << std::endl;
return 1;
}
at = check.tellp();
}
if ( (fin + std::streampos(sizeof(int))) != at ) {
std::cerr << "overwrite?
fin:" << fin << "
" << "at:" << at << std::endl;
return 1;
}
return 0;
}
In particular, it seems that std::ios_base::ate
does not move the initial output pointer to the end with the example seen above. Obviously this would result in the first write overwriting the beginning of the file (which is what caused my trouble).
It seems that either the implementation is incorrect or else cplusplus.com is incorrect ("The output position starts at the end of the file.") and cppreference.com is ambiguous ("seek to the end of stream immediately after open": which stream?).
There is obviously an easy workaround: just use stream.seekp(0, std::ios_base::end)
.
So my question is thus: is my code incorrect? Is the implementation incorrect? Are the reference sites incorrect? Any insight would be appreciated.
See Question&Answers more detail:os