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

时间:2022-02-11 00:07:00

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.

我正在开发一个程序,该程序大量使用“cout < strSomething;”来将信息记录到控制台。我需要修改程序,以便所有控制台输出都同时到达控制台和文件。虽然我可以在我们的代码中修改“cout <<”,但是也有几个大型的第三方库也使用“cout <<”;由于这些库的许可,这些库不能被修改——因此修改对“cout <”的所有引用不是一个解决方案。另外,使用“wtee”。由于命令行被执行的方式是不可能的。

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.

我正在使用Visual Studio 2008。我看到了谷歌组的帖子:重定向cout到文件,这似乎正是我想做的。唯一的问题是代码不能编译。在->overflow()和->sync()方法调用中,我得到C2248错误“无法访问受保护成员”。

Would anyone know how to get this code to compile? Or an alternate way of redirecting cout to both console and file simultaneously?

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

6 个解决方案

#1


1  

The sync calls can be replaced with pubsync. As for the overflow call I think that may be a typo. as it looks as if it should be a call to sputc.

同步调用可以被pubsync代替。至于溢流电话,我想可能是打错了。看起来好像是打给sputc的电话。

#2


12  

The boost::iostreams::tee_device is made for this

这个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;
}

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$ 

#3


2  

if you're desperate:

如果你是绝望:

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

this is a gross hack, but it usually works.

这是一种粗制滥造的手法,但通常管用。

#4


1  

What you can do is capture the std::cout.rdbuf() with a pointer to std::streambuf, then i think you should be able to write all the outputs to std::cout to some file.

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

#5


0  

you can just use a wrapper class to do so, somthing like this

您可以使用包装器类来实现这一点,类似这样的东西

#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");

declare cout like that and just change all your #include <iostream> to include this wrapper (remeber cout is external variable so you have to declere it in one of your source codes too).

像这样声明cout,然后修改所有的#include 来包含这个包装器(记住,cout是外部变量,所以必须在源代码中解密它)。

#6


0  

Sorry to warm this up so late, but this here should be a solution with redirection of cout to a teebuffer based on Dietmar Kühl's solution on Google groups.

很抱歉这么晚才把它热身,但这应该是一个解决方案,将cout重定向到teebuffer,基于Dietmar Kuhl在谷歌组上的解决方案。

Usage is simply

使用很简单

GetSetLog log("myfile.log");

During the lifetime of the object "log" everything will be written to both cout/cerr and file

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

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

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

#1


1  

The sync calls can be replaced with pubsync. As for the overflow call I think that may be a typo. as it looks as if it should be a call to sputc.

同步调用可以被pubsync代替。至于溢流电话,我想可能是打错了。看起来好像是打给sputc的电话。

#2


12  

The boost::iostreams::tee_device is made for this

这个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;
}

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$ 

#3


2  

if you're desperate:

如果你是绝望:

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

this is a gross hack, but it usually works.

这是一种粗制滥造的手法,但通常管用。

#4


1  

What you can do is capture the std::cout.rdbuf() with a pointer to std::streambuf, then i think you should be able to write all the outputs to std::cout to some file.

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

#5


0  

you can just use a wrapper class to do so, somthing like this

您可以使用包装器类来实现这一点,类似这样的东西

#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");

declare cout like that and just change all your #include <iostream> to include this wrapper (remeber cout is external variable so you have to declere it in one of your source codes too).

像这样声明cout,然后修改所有的#include 来包含这个包装器(记住,cout是外部变量,所以必须在源代码中解密它)。

#6


0  

Sorry to warm this up so late, but this here should be a solution with redirection of cout to a teebuffer based on Dietmar Kühl's solution on Google groups.

很抱歉这么晚才把它热身,但这应该是一个解决方案,将cout重定向到teebuffer,基于Dietmar Kuhl在谷歌组上的解决方案。

Usage is simply

使用很简单

GetSetLog log("myfile.log");

During the lifetime of the object "log" everything will be written to both cout/cerr and file

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

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

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