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

发布于 2024-11-06 05:02:40 字数 526 浏览 4 评论 0原文

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

我使用的是 Visual Studio 2008。我在 Google 网上论坛:将 cout 重定向到文件< 中看到了该帖子< /a>,这似乎正是我想做的。唯一的问题是代码无法编译。我在 ->overflow() 和 ->sync() 方法调用上收到 C2248 错误“无法访问受保护的成员”。

有人知道如何编译这段代码吗?或者同时将 cout 重定向到控制台和文件的替代方法?

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?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

清风挽心 2024-11-13 05:02:40

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$ 

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$ 
ぃ双果 2024-11-13 05:02:40

这很容易扩展到其他流。

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

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
伪心 2024-11-13 05:02:40

如果你绝望了:

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

这是一个粗俗的黑客,但它通常有效。

if you're desperate:

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

this is a gross hack, but it usually works.

乖不如嘢 2024-11-13 05:02:40

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

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.

守望孤独 2024-11-13 05:02:40

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

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.

青瓷清茶倾城歌 2024-11-13 05:02:40

您可以使用包装器类来执行此操作,像这样

#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 以包含此包装器(请记住 cout 是外部变量,因此您必须也在您的源代码之一中解密它)。

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).

颜漓半夏 2024-11-13 05:02:40

抱歉这么晚才热身,但这应该是一个基于 Dietmar Kühl 在 Google 群组上的解决方案将 cout 重定向到 teebuffer 的解决方案。

用法很简单

GetSetLog log("myfile.log");

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

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

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.

Usage is simply

GetSetLog log("myfile.log");

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

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

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文