According to this C++ reference: http://www.cplusplus.com/reference/fstream/ofstream/ofstream/, the default open mode for std::ofstream
is ios_base::out
and it mentions no implict other modes. Therefore I would expect that if I overwrite a large file with a small file, the "exceeding" part of the large file should stay untouched and only the first part of the file should be replaced by the new, shorter data.
On the other hand, the Apache C++ Standard Library User's Guide (http://stdcxx.apache.org/doc/stdlibug/30-3.html) states in the note to paragraph 30.3.1.2: "For output file streams the open mode out is equivalent to out|trunc, that is, you can omit the trunc flag. For bidirectional file streams, however, trunc must always be explicitly specified."
I have tried this code:
#include <fstream>
int main()
{
std::ofstream aFileStream("a.out", std::ios_base::out);
aFileStream << "Hello world!";
aFileStream.close();
std::ofstream aFileStream2("a.out", std::ios::out);
aFileStream2 << "Bye!";
aFileStream2.close();
}
Both, with g++ 8.1 on Windows and g++ 6.3 on Linux, the Apache documentation seems to be right. The large file is truncated, nothing remains after writing the shorter string with the second file stream.
Why is it like that? Is cplusplus.com wrong? Or on what does the behaviour depent?
Per [ofstream.cons]/itemdecl:2:
explicit basic_ofstream(const char* s, ios_base::openmode mode = ios_base::out);
Therefore, the default mode for ofstream
is out
. However, per [tab:filebuf.open.modes], out
and out | trunc
both correspond to the stdio equivalent "w"
, so they are equivalent. Per C11 7.21.5.3:
w
: truncate to zero length or create text file for writing
Thus, it is correct to say that the default mode is out
, and it is also correct to say that the default mode is equivalent to out | trunc
. This is guaranteed behavior.
On the other hand, per [fstream.cons]/itemdecl:2:
explicit basic_fstream( const char* s, ios_base::openmode mode = ios_base::in | ios_base::out);
Therefore, the default mode for fstream
is in | out
. Per [tab:filebuf.open.modes], in | out
corresponds to "r+"
, while in | out | trunc
corresponds to "w+"
, so they are not equivalent. Per C11 7.21.5.3:
r+
: open text file for update (reading and writing)w+
: truncate to zero length or create text file for update
Therefore, fstream
does not truncate unless you specify trunc
.
Note that if the desired file does not exist, r+
will fail instead of creating the file. In contrast, w
and w+
both create a new file in this case.
(See also: fopen
on cppreference)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With