TIL - Split streams with boost::tee_device

Posted by Marcus Folkesson on Monday, May 15, 2023

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:

 1    #include <fstream>
 2    #include <iostream>
 3
 4    #include <boost/iostreams/tee.hpp>
 5    #include <boost/iostreams/stream.hpp>
 6
 7    using std::ostream;
 8    using std::ofstream;
 9    using std::cout;
10    using std::endl;
11
12    using boost::iostreams::tee_device;
13    using boost::iostreams::stream;
14
15    // Create typedefs to avoid too long type declarations later on
16    typedef tee_device<ostream, ofstream> TeeDevice;
17    typedef stream<TeeDevice> TeeStream;
18
19    int main()
20    {
21        // Create streams and connect them to a file and stdout
22        ofstream ofs("stdout.log");
23        ostream tmp(cout.rdbuf());
24
25        TeeDevice logdevice(tmp, ofs);
26        TeeStream logger(logdevice);
27
28        // Set streambuffer for cout 
29        cout.rdbuf(logger.rdbuf());
30
31        // Make some logs
32        cout << "Log output to both stdout and file." << endl;
33    }

Compile and test

1    [08:35:24]marcus@goliat:~/tmp/tee$ g++ main.cpp -o main && ./main
2    Log output to both stdout and file.
3
4    [08:56:09]marcus@goliat:~/tmp/tee$ cat stdout.log 
5    Log output to both stdout and file.