2

I have a Qt console application. All communication with the user goes over two streams:

QTextStream in(stdin);
QTextStream out(stdout);

Now I want to log the whole session to a file, but I don't want to add a log output on every location where the streams are used.

Is there an easy way to "tee" the data of both streams to the console and to a file?

The app has to run on Windows.

Thomas Klier
  • 449
  • 4
  • 16
  • 4
    Yes, you can create class inheriting from std::streambuf, which "tee"'s your stream and provide it to QTextStream instead of **stdin/stdout**... [a simple howto](http://wordaligned.org/articles/cpp-streambufs) is actually the first google result if you google for "c++ tee streambuf". – user1810087 Dec 18 '17 at 11:18

1 Answers1

2

I suggest a very simple solution, but c++14 is recommended. I would wrap QTextStream this way (output only as example):

#include <QTextStream>
#include <QFile>

class OutTeeTextStream
{
public:
    OutTeeTextStream()
    {
        logfilestream = 0;
        stdoutstream = new QTextStream(stdout);
        file.setFileName("/tmp/outlog.log");
        if(file.open(QFile::Append))
        {
            logfilestream = new QTextStream(&file);
        }
    }
    ~OutTeeTextStream()
    {
        file.close();
        delete stdoutstream;
        delete logfilestream;
    }
    OutTeeTextStream &operator<<(auto data)
    {
        (*stdoutstream) << data;
        if(logfilestream != 0)
        {
            (*logfilestream) << data;
        }
        return (*this);
    }
private:
    QTextStream * stdoutstream;
    QTextStream * logfilestream;
    QFile file;
};

As you can see, the wrapper holds two QTextStream instances and provides a stream insertion operator, which basically broadcasts data to each of them.

Not using c++14 (e.g. c++11) will result in complaints about use of ‘auto’ in parameter declaration. In this case, one had to declare/define every insertion (and extraction) operator overload (about fifteen / seventeen in QTextStream).

Refactoring would consist of replacing every QTextStream(stdout) with OutTeeTextStream().

p-a-o-l-o
  • 9,807
  • 2
  • 22
  • 35