4

I am trying to append a sequence of matrices to disk as CSV and have found that using ios::ate overwrites any existing file created previously. To illustrate this problem via a simplified model, a second call to the function write_nums() below results in the loss of anydata written in the first call. Is there a way to fix this?

The solution to this question previously given in ofstream open modes: ate vs app does not seem optimal as it only works provided the file to which the output is directed already exists.

void write_nums()
{
    std::ofstream out_file;

    out_file.open("test.txt", std::ofstream::ate);
    if (!out_file.good())
    {
        std::cerr << "Error while opening output file!" << '\n';
    }
    out_file.seekp(0, std::ios::end);
    out_file << "{";
    for (int i = 0; i < 10; ++i)
    {
        out_file << i << ',';
    }
    out_file.seekp(-1, std::ios::end);
    out_file << "}";
}
amandini
  • 41
  • 2
  • "it only works provided the file to which the output is directed already exists", no, with `app` flag the file will be created if it does not exist. – anastaciu Jul 14 '20 at 11:20

2 Answers2

2

That happens because ios_base::ate is an additional flag, the "primary" flags that determine the open mode are in, out and app.

Valid open mode flag combinations are listed in [input.output]/2.

Since you specified none of in, out or app, ofstream::open defaults to mode out, which is equivalent of "w", which truncates the file.

ios_base::ate is useful in combination with ios_base::in for "tailing" a file.

For appending to a file there is ios_base::app which matches your situation exactly.

rustyx
  • 80,671
  • 25
  • 200
  • 267
  • Doesn't `std::ofstream` always default to `std::ios::out` and `std::ifstream` to `std::ios::in`? – Amal K Jul 14 '20 at 11:17
2

std::ofstream::ate truncates the existing file. One of the answers for the question you have linked also mentions it, you have to combine ate with in to avoid truncation. Using app won't let you play with the seek.


void write_nums()
{
    std::ofstream out_file("test.txt", std::ofstream::ate | std::ofstream::in);
    if (!out_file.good())
    {
        std::cerr << "Error while opening output file!" << '\n';
    }
    out_file.seekp(0, std::ios::end);
    out_file << "{";
    for (int i = 0; i < 10; ++i)
    {
        out_file << i << ',';
    }
    out_file.seekp(-1, std::ios::end);
    out_file << "}";
}
Amal K
  • 4,359
  • 2
  • 22
  • 44