Search code examples
c++ofstreamstreambuf

Use multiple ofstreams to write to a single output file in c++


I have class Writer that has two ofstream members.
Both streams are associated with the same output file. I'd like to use both streams in Writer::write method, but to make sure that each stream writes to the end of the real output file.

Code

class my_ofstream1:
    public ofstream
{
    // implement some functions.
    // using internal, extended type of streambuf
};

class my_ofstream2:
    public ofstream
{
    // implement some functions.
    // using internal, extended type of streambuf 
    // (not the same type as found in my_ofstream1)
};


class Writer
{
public:

    void open(string path)
    {
        f1.open(path.c_str(),ios_base::out); f2.open(path.c_str(),ios_base::out);
    }

    void close()
    {
        f1.close(); f2.close();
    }

    void write()
    {
        string s1 = "some string 1";
        string s2 = "some string 2";
        f1.write(s1.c_str(), s1.size());

        // TBD - ensure stream f2 writes to the end of the actual output file
        assert(f1.tellp() == f2.tellp());
        f2.write(s2.c_str(), s2.size());
    }

private:
    my_ofstream1 f1;
    my_ofstream1 f2;
};

void main()
{
    Writer w;
    w.open("some_file.txt");
    w.write();
    w.close();
}

Questions

How to ensure f2 is in sync with f1? meaning, before writing, stream offset of f2 must be in sync with stream offset of f1 and vice versa?
I can't use function std::ios::rdbuf since each ofstream uses special derived streambuf. so by using rdbuf() I'll lose the necessary functionality.
I tried using some of the techniques found in Synchronizing Streams topic but could not make it happen.


Solution

  • This looks like both of your classes use the filtering streambuf idiom. In any case, don't derive your classes from std::ofstream, but directly from ostream, and have them both use the same std::filebuf object. If you are using the filtering streambuf idiom, don't let your filtering streambuf's buffer; leave that to the final std::filebuf.

    In other words, your "internal, extended type of streambuf" should contain a pointer to the final sink, which will be a filebuf (but your filtering streambufs don't need to know this). Functions like sync, they just pass on to the final destination, and they should never establish a buffer themselves, but pass everything on to the filebuf.