Search code examples
c++visual-studio-2012fstream

ofstream open modes: ate vs app


This question asks the difference between app and ate and both the answers and cppreference imply that the only difference is that app means that the write cursor is put at the end of the file before each write operation, whereas ate means that the write cursor is put at the end of the file only when opening.

What I'm actually seeing (in VS 2012) is that specifying ate discards the contents of an existing file, whereas app does not (it appends new content to the previously existing content). In other words, ate seems to imply trunc.

The following statement appends "Hello" to an existing file:

ofstream("trace.log", ios_base::out|ios_base::app) << "Hello\n";

But the following statement replaces the contents of the file with just "Hello":

ofstream("trace.log", ios_base::out|ios_base::ate) << "Hello\n";

The MSDN documentation for VS 6.0 implies that shouldn't happen (but this sentence seems to have been withdrawn in later versions of Visual Studio):

ios::trunc: If the file already exists, its contents are discarded. This mode is implied if ios::out is specified, and ios::ate, ios::app, and ios:in are not specified.


Solution

  • You need to combine std::ios::in with std::ios::ate then seek the end of the file and append the text:

    Consider I have a file "data.txt" which contains this line:

    "Hello there how are you today? Ok fine thanx. you?"
    

    Now I open it:

    1: std::ios::app:

    std::ofstream out("data.txt", std::ios::app);
    
    out.seekp(10); // I want to move the write pointer to position 10
    
    out << "This line will be appended to the end of the file";
    
    out.close();
    

    The result is not what I wanted: No moving the write pointer but only the text is always appended to the end.

    2: std::ios::ate:

    std::ofstream out2("data.txt", std::ios::ate);
    
    out2 << "This line will be ate to the end of the file";
    
    out2.close();
    

    The result above is not what I wanted no text appended but the content is truncated!

    To solve it combine ate with in:

    std::ofstream out2("data.txt", std::ios::ate | std::ios::in);
    
    out2 << "This line will be ate to the end of the file";
    
    out2.close();
    

    Now the text is appended to the end but what is the difference:

    As I said app doesn't allow moving the write pointer but ate does.

    std::ofstream out2("data.txt", std::ios::ate | std::ios::in);
    
    out2.seekp(5, std::ios::end); // add the content after the end with 5 positions.
    
    out2 << "This line will be ate to the end of the file";
    
    out2.close();
    

    Above we can move the write pointer to the position we want while with app we cannot.