I'm working on a program that makes heavy use of "cout << strSomething;" to log information to the console. I need to modify the program so that all console output goes to both the console AND a file. Although I can modify the "cout <<" in our code, there are several large third party libraries that also use "cout <<"; those libraries cannot be modified due to their licenses - so modifying all references to "cout <<" is not a solution. Also, the use of "wtee.exe" isn't possible due to the manner in which the command lines are executed.
I am using Visual Studio 2008. I've seen the posting at Google Groups: redirect cout to file, which appears to do EXACTLY what I want to do. The only problem is that the code won't compile. I get C2248 errors "cannot access protected member" on the ->overflow() and ->sync() method calls.
Would anyone know how to get this code to compile? Or an alternate way of redirecting cout to both console and file simultaneously?
The boost::iostreams::tee_device
is made for this
#include <boost/iostreams/stream.hpp>
#include <boost/iostreams/tee.hpp>
#include <fstream>
#include <iostream>
int
main()
{
typedef boost::iostreams::tee_device<std::ostream, std::ofstream> Tee;
typedef boost::iostreams::stream<Tee> TeeStream;
std::ofstream file( "foo.out" );
Tee tee( std::cout, file );
TeeStream both( tee );
both << "this goes to both std::cout and foo.out" << std::endl;
return 0;
}
sample invocation:
samm$ ./a.out
this goes to both std::cout and foo.out
samm$ cat foo.out
this goes to both std::cout and foo.out
samm$
This easily extends to additional streams.
OstreamFork.hpp -- Distribute data to 2 streams simultaneously
#include <iomanip>
#include <fstream>
#include <iostream>
using namespace std ;
class ostreamFork // Write same data to two ostreams
{
public:
ostream& os1 ;
ostream& os2 ;
ostreamFork( ostream& os_one , ostream& os_two )
: os1( os_one ) ,
os2( os_two )
{}
} ;
// For data: int, long , ...
template <class Data>
ostreamFork& operator<<( ostreamFork& osf , Data d )
{
osf.os1 << d ;
osf.os2 << d ;
return osf ;
}
// For manipulators: endl, flush
ostreamFork& operator<<( ostreamFork& osf , ostream& (*f)(ostream&) )
{
osf.os1 << f ;
osf.os2 << f ;
return osf ;
}
// For setw() , ...
template<class ManipData>
ostreamFork& operator<<( ostreamFork& osf , ostream& (*f)(ostream&, ManipData ) )
{
osf.os1 << f ;
osf.os2 << f ;
return osf ;
}
TestOstreamFork.cpp:
#include "stdafx.h"
#include <fstream>
using namespace std ;
#include "ostreamFork.hpp"
int main(int argc, char* argv[])
{
ofstream file( "test2.txt" ) ;
ostreamFork osf( file , cout ) ;
for ( int i = 0 ; i < 10 ; i++ )
{
osf << i << setw(10) << " " << 10*i << endl ;
}
return 0 ;
}
Output to both cout and test2.txt:
0 0
1 10
2 20
3 30
4 40
5 50
6 60
7 70
8 80
9 90
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