TIL - Split streams with boost::tee_device

TIL - Split streams with boost::tee_device

TIL, Today I Learned, is more of a "I just figured this out: here are my notes, you may find them useful too" rather than a full blog post

Split streams could be useful if you want the same output to appear in more than one stream at once. Boost support tee_device, which works pretty much as the tee(1) [1] command line tool. Everything written to that device is splitted up and written into two streams. Think of the letter T.

/media/boost-teedevice.png

Here is an example of how to let everything written to cout and also be logged into a file. This is achieved by change the streambuffer for cout to instead use the logger stream:

    #include <fstream>
    #include <iostream>

    #include <boost/iostreams/tee.hpp>
    #include <boost/iostreams/stream.hpp>

    using std::ostream;
    using std::ofstream;
    using std::cout;
    using std::endl;

    using boost::iostreams::tee_device;
    using boost::iostreams::stream;

    // Create typedefs to avoid too long type declarations later on
    typedef tee_device<ostream, ofstream> TeeDevice;
    typedef stream<TeeDevice> TeeStream;

    int main()
    {
        // Create streams and connect them to a file and stdout
        ofstream ofs("stdout.log");
        ostream tmp(cout.rdbuf());

        TeeDevice logdevice(tmp, ofs);
        TeeStream logger(logdevice);

        // Set streambuffer for cout 
        cout.rdbuf(logger.rdbuf());

        // Make some logs
        cout << "Log output to both stdout and file." << endl;
    }

Compile and test

    [08:35:24]marcus@goliat:~/tmp/tee$ g++ main.cpp -o main && ./main
    Log output to both stdout and file.

    [08:56:09]marcus@goliat:~/tmp/tee$ cat stdout.log 
    Log output to both stdout and file.