自定义C ++ cout类 - 输出到控制台和日志文件

时间:2011-05-09 20:39:09

标签: c++ console stdout cout

我正在制作一个大量使用“cout<< strSomething”的程序。将信息记录到控制台。我需要修改程序,以便所有控制台输出都转到控制台和文件。虽然我可以修改“cout<<”在我们的代码中,有几个大的第三方库也使用“cout<<”;这些库由于其许可证而无法修改 - 因此修改所有对“cout<<”的引用不是解决方案。此外,由于命令行的执行方式,无法使用“wtee.exe”。

我正在使用Visual Studio 2008.我在Google Groups: redirect cout to file看到了帖子,这似乎完全符合我的要求。唯一的问题是代码不会编译。我在 - > overflow()和 - > sync()方法调用上得到C2248错误“无法访问受保护的成员”。

有谁知道如何编译这段代码?或者将cout同时重定向到控制台和文件的另一种方法是什么?

7 个答案:

答案 0 :(得分:12)

为此

制作了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$ 

答案 1 :(得分:2)

如果你绝望了:

#define protected public
#include <iostream>
#undef protected

这是一个严重的黑客行为,但它通常有效。

答案 2 :(得分:2)

这很容易扩展到其他流。

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

答案 3 :(得分:1)

sync来电可以替换为pubsync。至于overflow电话,我认为这可能是一个错字。因为看起来它应该是对sputc的调用。

答案 4 :(得分:1)

您可以做的是使用指向std::cout.rdbuf()的指针捕获std::streambuf, 那么我认为你应该能够将std::cout的所有输出写入某个文件。

答案 5 :(得分:0)

你可以使用包装类来做到这一点,就像这样

#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>以包含此包装器(记住cout是外部变量,因此您必须在其中一个源代码中对其进行删除)。

答案 6 :(得分:0)

很抱歉这么晚才热身,但这里应该是一个解决方案,根据DietmarKühl的Google群组解决方案将cout重定向到teebuffer。

用法很简单

GetSetLog log("myfile.log");

在对象“log”的生命周期中,所有内容都将写入cout / cerr和file

https://sourceforge.net/p/getset/code/ci/master/tree/GetSet/GetSetLog.hxx