Search code examples
c++fstreamstringbuffersstreamfilebuf

Using same stream object to write to filestream or stringstream


I am trying to use an ostream object to write to either to a filestream of stringstream based user input (similar to fmemopen in Linux).

I realized that ostream doesnt take stringstream or fstream objects but instead takes stringbug or filebuf.

I tried the following code:

    char content[] = "This is a test";
    if (isFile)
    {
        filebuf fp;
        fp.open(filename, ios::out);
        ostream os(&fp);
        os << content;
        fp.close();
    }
    else
    {
        stringbuf str;
        ostream os(&str);
        os << content;
    }

This works fine, in the if else condition but I would like to use the ostream os, as os << content, outside the if else condition. The issue is however I am unable to globally define ostream os since there is no such constructor for ostream.

Is there a way to get around this?


Solution

  • This can be handled a couple of different ways.

    Using a helper function:

    void write(ostream &os, const char *content)
    {
        os << content
    }
    
    ...
    
    char content[] = "This is a test";
    if (isFile)
    {
        ofstream ofs(filename);
        write(ofs, content);
    }
    else
    {
        ostringstream oss;
        write(oss, content);
        string s = oss.str();
        // use s as needed...
    }
    

    Alternatively, using a lambda:

    char content[] = "This is a test";
    auto write = [](ostream &os, const char *content){ os << content; }
    
    if (isFile)
    {
        ofstream ofs(filename);
        write(ofs, content);
    }
    else
    {
        ostringstream oss;
        write(oss, content);
        string s = oss.str();
        // use s as needed...
    }
    

    Using a pointer instead:

    char content[] = "This is a test";
    std::unique_ptr<ostream> os;
    
    if (isFile)
        os = std::make_unique<ofstream>(filename);
    else
        os = std::make_unique<ostringstream>();
    
    *os << content;
    
    if (!isFile)
    {
        string s = static_cast<ostringstream*>(os.get())->str(); // or: static_cast<ostringstream&>(*os).str()
        // use s as needed...
    }