Пользовательский класс c++ cout-вывод в консоль и файл журнала
Я работаю над программой, которая активно использует "cout
Я использую Visual Studio 2008. Я видел сообщение в группы Google: перенаправить cout в файл, который, похоже, делает именно то, что я хочу сделать. Единственная проблема в том, что код не компилируется. Я получаю ошибки C2248 "не могу получить доступ к защищенному члену" при вызовах метода- >overflow() и - >sync ().
кто-нибудь знает, как заставить этот код компилироваться? Или альтернативный способ перенаправления cout на консоль и файл одновременно?
7 ответов
на sync
вызовы могут быть заменены на pubsync
. Что касается overflow
звонок я думаю, что это может быть опечатка. как это выглядит, как будто это должен быть вызов sputc
.
на boost::iostreams::tee_device
для этого
#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;
}
пример вызова:
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$
Если вы в отчаянии:
#define protected public
#include <iostream>
#undef protected
это грубый хак, но он обычно работает.
что вы можете сделать, это захватить std::cout.rdbuf()
с указателем std::streambuf
,
тогда я думаю, что вы должны иметь возможность записывать все выходы в std::cout
в какой-нибудь файл.
Это легко распространяется на дополнительные потоки.
OstreamFork.hpp -- распределить данные по 2 потокам одновременно
#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 ;
}
выход как на cout, так и на test2.txt:
0 0
1 10
2 20
3 30
4 40
5 50
6 60
7 70
8 80
9 90
вы можете просто использовать класс-оболочку для этого, что-нибудь подобное
#include <iostream>
#include <fstream>
...
class streamoutput
{
std::ofstream fileoutput;
public:
streamoutput(char*filename){
fileoutput.open(filename);
}
~streamoutput(){
fileoutput.close();
}
template<class TOut> streamoutput& operator <<(const TOut& data)
{
fileoutput << data;
std::cout << data;
return this;
}
};
extern streamoutput cout("logfile.log");
объявить cout как это и просто изменить все ваши #include <iostream>
чтобы включить эту обертку (remeber cout-внешняя переменная, поэтому вам также нужно декларировать ее в одном из ваших исходных кодов).
Извините, что так поздно, но это должно быть решение с перенаправлением cout на teebuffer на основе решения Дитмара Кюля в Google groups.
использование просто
GetSetLog log("myfile.log");
в течение жизни объекта " log " все будет записано как в cout/cerr, так и в file
https://sourceforge.net/p/getset/code/ci/master/tree/GetSet/GetSetLog.hxx