24

I have 10 files need to be open for write in sequence. Can I have one fstream to do this? Do I need to do anything special (except flush()) in between each file or just call open(file1, fstream::out | std::ofstream::app) for a each file and close the stream at the end of all 10 files are written.

5YrsLaterDBA
  • 33,370
  • 43
  • 136
  • 210

3 Answers3

30

You will need to close it first, because calling open on an already open stream fails. (Which means the failbit flag is set to true). Note close() flushes, so you don't need to worry about that:

std::ofstream file("1");
// ...
file.close();
file.clear(); // clear flags
file.open("2");
// ...

// and so on

Also note, you don't need to close() it the last time; the destructor does that for you (and therefore also flush()'s). This may make a nice utility function:

template <typename Stream>
void reopen(Stream& pStream, const char * pFile,
            std::ios_base::openmode pMode = ios_base::out)
{
    pStream.close();
    pStream.clear();
    pStream.open(pFile, pMode);
}

And you get:

std::ofstream file("1");
// ...
reopen(file, "2")
// ...

// and so on
GManNickG
  • 494,350
  • 52
  • 494
  • 543
  • 5
    It is better to insert a call to `clear()` between the calls to `close()` and `open()`, because state flags are not cleared. See http://gcc.gnu.org/onlinedocs/libstdc++/faq.html#faq.stream_reopening_fails for a detailed explanation. – Danilo Piazzalunga Feb 18 '10 at 20:49
  • Is there something similar for `FILE` variables? I mean multiple reuse. Aspecialy for writing to them. `fclose()` doesn't help. – Alexandru Barbarosie Jun 24 '13 at 01:04
2

Yes, but you must to close the fstream each time before opening the next file with it.

However, it's better to use a new scoped fstream object for each file access to take advantage of the constructor and destructor behaviors:

struct {
    const char *filename;
    void (*operation)(fstream&);
} filelist[] = {
    { "file1", callback1 },
    { "file2", callback2 },
    ...
    { "file10", callback10 },
};

for (int i = 0; i < 10; ++i) {
    fstream f(filelist[i].filename);
    filelist[i].operation(f);
}

In the code sample above, the fstream is flushed and closed each time through the for loop because the destructor is called when the object loses scope. The fstream is passed by reference to a callback function so that the operations can be handled on a per file basis without a nasty switch statement. If the operation is the same for each file, then that construct can be eliminated.

Judge Maygarden
  • 26,961
  • 9
  • 82
  • 99
2

Closing a stream implies flush(), so as long as you close() each stream before you open the next one you should be fine.

John Knoeller
  • 33,512
  • 4
  • 61
  • 92