2

Redirecting cout or cerr to a file is easy enough. I can use this to redirect third party output to a file. However, after I have redirected the third party output to a file, how do I then use cout myself to output to the console?

inetknght
  • 4,300
  • 1
  • 26
  • 52
  • 4
    What is "third party output"? – Kerrek SB Jan 11 '13 at 22:36
  • Typically debug chatter from code another team in the building wrote. I suppose I could poke them to give me an interface to have them output somewhere else. But I wanted to learn if there's another way to do it in case I came into a situation where I legitimately couldn't influence the code being called. – inetknght Feb 11 '13 at 15:38

2 Answers2

4

You save the buffer and restore it later:

std::streambuf *buf = std::cout.rdbuf(); //save
// Do other stuff
std::cout.rdbuf(buf); // restore
Jesse Good
  • 50,901
  • 14
  • 124
  • 166
  • What if the third party lib has other threads which make calls to cout? – inetknght Jan 12 '13 at 00:42
  • 1
    @inetknght: [See this SO question](http://stackoverflow.com/questions/6374264/is-cout-synchronized-thread-safe) for some more information about differences between C++03 and C++11, but basically you will have to manage synchronization yourself and make sure multiple threads are not writing to cout at the same time. – Jesse Good Jan 12 '13 at 08:23
4

I'm a great fan of RAII, so I once wrote this small helper class. It will redirect the stream until it goes out of scope, at which point it restores the original buffer. Quite handy. :)

class StreamRedirector {
public:
    explicit StreamRedirector(std::ios& stream, std::streambuf* newBuf) :
        savedBuf_(stream.rdbuf()), stream_(stream)
    {
        stream_.rdbuf(newBuf);
    }

    ~StreamRedirector() {
        stream_.rdbuf(savedBuf_);
    }

private:
    std::streambuf* savedBuf_;
    std::ios& stream_;
};

Can be used like this:

using namespace std;
cout << "Hello stdout" << endl;
{
    ofstream logFile("log.txt");
    StreamRedirector redirect(cout, logFile.rdbuf());
    cout << "In log file" << endl;
}
cout << "Back to stdout" << endl;
lethal-guitar
  • 4,438
  • 1
  • 20
  • 40
  • I like your use of anonymous scoping to take care of it. I was already using that for other RAII objects. Barring a better solution, I'd say this will have to do. It still doesn't solve other threads' use especially if there's no syncing mechanism for those threads. – inetknght Jan 16 '13 at 21:36
  • Well, as long as the other threads do not change any of the `rdbuf`s, and you do the redirection before you call any potentially thread-spawning libraries, there should be no problem, I'd think? Unless I'm missing something here.. – lethal-guitar Jan 16 '13 at 22:10
  • I think that would be implementation-dependent. I don't know of a guarantee that a thread gets its own copy of cout's state upon thread spawn? – inetknght Jan 17 '13 at 15:50