In my application, I want to redirect the output that would normally go to the stdout stream to a function I define. I read that you can redirect stdio to a file, so why not to a function?
For example:
void MyHandler( const char* data ); //<<Magical redirection code>> printf( "test" ); std::cout << "test" << std::endl; //MyHandler should have been called with "test" twice, at this point
Redirecting stdout and stderr to a file: The I/O streams can be redirected by putting the n> operator in use, where n is the file descriptor number. For redirecting stdout, we use “1>” and for stderr, “2>” is added as an operator.
The dup2() system function is used to create a copy of an existing file descriptor. In Linux, there are 3 standard file descriptors. They are: stdin: This is the standard input file descriptor.
The command | tee file pattern (which includes the tee command) redirects the standard output of the command to a file and overwrites its contents. Then, it displays the redirected output in the terminal.
@Konrad Rudolph is right, you can totally do this, easily, at least for cout/cerr/clog. You don't even need your own streambuf implementation, just use an ostringstream.
// Redirect cout. streambuf* oldCoutStreamBuf = cout.rdbuf(); ostringstream strCout; cout.rdbuf( strCout.rdbuf() ); // This goes to the string stream. cout << "Hello, World!" << endl; // Restore old cout. cout.rdbuf( oldCoutStreamBuf ); // Will output our Hello World! from above. cout << strCout.str();
Same thing works for cerr and clog, but in my experience that will NOT work for stdout/stderr in general, so printf won't output there. cout goes to stdout, but redirecting cout will not redirect all stdout. At least, that was my experience.
If the amount of data is expected to be small, the freopen/setbuf thing works fine. I ended up doing the fancier dup/dup2 thing redirecting to a pipe.
Update: I wrote a blog post showing the dup2 method I ended up using, which you can read here. It's written for OS X, but might work in other Unix flavors. I seriously doubt it would work in Windows. Cocoa version of the same thing here.
All the other answers are wrong. You can do this, and you don’t need to resort to freopen
, nor to any other C or nonstandard functions.
Instead, you need to create your own std::streambuf
implementation, i.e. your own stream buffer.
Once you have that, you can redirect the cout
stream by switching the buffer:
your_stream_buffer new_buffer; streambuf* old_buffer = cout.rdbuf(&new_buffer); cout << "Hello"; // This will be redirected to `new_buffer`. // Restore original buffer: cout.rdbuf(old_buffer);
Since I’ve never done that myself I cannot tell you exactly how the implementation of streambuf
has to look like. My advice is to have a look at the documentation and do a dummy implementation that prints diagnostics for all implemented functions. This should help figuring out how the class works.
Alternatively, have a look at a C++ reference book of your choice that describes the streambuf
class.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With