如何将 clog to tee 重新定义为原始 clog 和日志文件?

发布于 2024-07-23 02:32:59 字数 446 浏览 10 评论 0原文

我在这里看到了一个有用的开始:

http://www.cs。 technion.ac.il/~imaman/programs/teestream.html

并且它非常适合创建一个同时进入 clog 和日志文件的新流。

但是,如果我尝试将 clog 重新定义为新流,它将不起作用,因为新流具有与 clog 相同的 rdbuf() ,因此以下内容无效:

clog.rdbuf(myTee.rdbuf());

那么如何修改 tee 类以拥有自己的 rdbuf( ) 那么哪个可以成为 clog 的目标呢?

谢谢。

-威廉

I saw a useful start here:

http://www.cs.technion.ac.il/~imaman/programs/teestream.html

And it works great to make a new stream which goes to both clog and a log file.

However, if I try to redefine clog to be the new stream it does not work because the new stream has the same rdbuf() as clog so the following has no effect:

clog.rdbuf(myTee.rdbuf());

So how can I modify the tee class to have its own rdbuf() which can then be the target of clog?

Thanks.

-William

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

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

发布评论

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

评论(4

余生共白头 2024-07-30 02:32:59

如果您确实想继续使用 std::clog 作为 tee,而不是将输出发送到不同的流,则需要降低一级:从 Streambuf 派生,而不是从 ostream 派生。 然后您可以执行以下操作:

fstream logFile(...);
TeeBuf tbuf(logFile.rdbuf(), clog.rdbuf());
clog.rdbuf(&tbuf);

有关如何派生您自己的streambuf类的更多信息,请参阅此处

If you really want to keep using std::clog for the tee instead of sending output to a different stream, you need to work one level lower: Instead of deriving from ostream, derive from streambuf. Then you can do this:

fstream logFile(...);
TeeBuf tbuf(logFile.rdbuf(), clog.rdbuf());
clog.rdbuf(&tbuf);

For more information on how to derive your own streambuf class, see here.

久光 2024-07-30 02:32:59

您不想做您想做的事情,因为“tee”在 rdbuf 级别不起作用。 因此,将 rdbuf 设置为其他值将不起作用,输出只会进入一个流。

您需要遵循该示例:

例如,

fstream clog_file(...);
xstream clog_x(...);
TeeStream clog(clog_file, clog_x);

然后在各处使用木屐而不是原来的木屐。

You don't want to do what your've trying to do because the 'tee' is not working at the rdbuf level. So setting the rdbuf to something else will not work, the output will only go to one stream.

You need to follow there example:

e.g.

fstream clog_file(...);
xstream clog_x(...);
TeeStream clog(clog_file, clog_x);

then use clog everywhere instead of your original clog.

这是我创建的课程,似乎可以完成这项工作,感谢所有提供帮助的人!

-威廉

class TeeStream : public std::basic_filebuf<char, std::char_traits<char> >
{
private:
  class FileStream : public std::ofstream {
  public:
    FileStream()
      : logFileName("/my/log/file/location.log") {
      open(logFileName.c_str(), ios::out | ios::trunc);

      if (fail()) {
        cerr << "Error: failed to open log file: " << logFileName << endl;
        exit(1);
      }
    }
    ~FileStream() {
      close();
    }

    const char *getLogFileName() const {
      return logFileName.c_str();
    }

  private:
    const string logFileName;

  };

public:
  typedef std::char_traits<char> traits;
  typedef std::basic_filebuf<char, traits> baseClass;

  TeeStream()
    :  baseClass(),
       _logOutputStream(),
       _clogBuf(clog.rdbuf()),
       _fileBuf(_logOutputStream.rdbuf()) {
    clog.rdbuf(this);
    _logOutputStream << "Log file starts here:" << endl;
  }
  ~TeeStream() {
    clog.rdbuf(_clogBuf);
  }

  int_type overflow(char_type additionalChar =traits::eof()) {
    const int_type eof = traits::eof();
    const char_type additionalCharacter = traits::to_char_type(additionalChar);
    const int_type result1 = _clogBuf->sputc(additionalCharacter);
    const int_type result2 = _fileBuf->sputc(additionalCharacter);

    if (traits::eq_int_type(eof, result1)) {
      return eof;
    } else {
      return result2;
    }
  }

  int sync() {
    const int result1 = _clogBuf->pubsync();
    const int result2 = _fileBuf->pubsync();

    if (result1 == -1) {
      return -1;
    } else {
      return result2;
    }
  }

private:
  FileStream _logOutputStream;
  streambuf * const _clogBuf;
  streambuf * const _fileBuf;

};

Here is the class I created that seems to do the job, thanks to all who helped out!

-William

class TeeStream : public std::basic_filebuf<char, std::char_traits<char> >
{
private:
  class FileStream : public std::ofstream {
  public:
    FileStream()
      : logFileName("/my/log/file/location.log") {
      open(logFileName.c_str(), ios::out | ios::trunc);

      if (fail()) {
        cerr << "Error: failed to open log file: " << logFileName << endl;
        exit(1);
      }
    }
    ~FileStream() {
      close();
    }

    const char *getLogFileName() const {
      return logFileName.c_str();
    }

  private:
    const string logFileName;

  };

public:
  typedef std::char_traits<char> traits;
  typedef std::basic_filebuf<char, traits> baseClass;

  TeeStream()
    :  baseClass(),
       _logOutputStream(),
       _clogBuf(clog.rdbuf()),
       _fileBuf(_logOutputStream.rdbuf()) {
    clog.rdbuf(this);
    _logOutputStream << "Log file starts here:" << endl;
  }
  ~TeeStream() {
    clog.rdbuf(_clogBuf);
  }

  int_type overflow(char_type additionalChar =traits::eof()) {
    const int_type eof = traits::eof();
    const char_type additionalCharacter = traits::to_char_type(additionalChar);
    const int_type result1 = _clogBuf->sputc(additionalCharacter);
    const int_type result2 = _fileBuf->sputc(additionalCharacter);

    if (traits::eq_int_type(eof, result1)) {
      return eof;
    } else {
      return result2;
    }
  }

  int sync() {
    const int result1 = _clogBuf->pubsync();
    const int result2 = _fileBuf->pubsync();

    if (result1 == -1) {
      return -1;
    } else {
      return result2;
    }
  }

private:
  FileStream _logOutputStream;
  streambuf * const _clogBuf;
  streambuf * const _fileBuf;

};
逆光飞翔i 2024-07-30 02:32:59

我只会使用 Boost iostreams 来做到这一点。

<代码>
#include
#include
#include
#include

int main(const int a_argc, const char *a_args[])
{
    namespace io = boost::iostreams;
    typedef io::tee_device<std::ofstream, std::ostream> TeeDevice;
    typedef io::stream<TeeDevice> TeeStream;

    std::ofstream flog("logFile.txt");
    //We need to copy clog, otherwise we get infinite recursion
    //later on when we reassign clog's rdbuf.
    std::ostream clogCopy(std::clog.rdbuf());

    TeeDevice logTee(flog, clogCopy);
    TeeStream logTeeStream(logTee);

    logTeeStream << "This text gets clogged and flogged." << std::endl;

    //Modify clog to automatically go through the tee.
    std::streambuf *originalRdBuf = std::clog.rdbuf(logTeeStream.rdbuf());  

    std::clog << "This text doesn't only get clogged, it's flogged too." << std::endl;

    std::clog.rdbuf(originalRdBuf);
    std::clog << "This text avoids flogging." << std::endl;
}

I would just use the Boost iostreams stuff to do it.


#include <iostream>
#include <fstream>
#include <boost/iostreams/tee.hpp>
#include <boost/iostreams/stream.hpp>

int main(const int a_argc, const char *a_args[])
{
    namespace io = boost::iostreams;
    typedef io::tee_device<std::ofstream, std::ostream> TeeDevice;
    typedef io::stream<TeeDevice> TeeStream;

    std::ofstream flog("logFile.txt");
    //We need to copy clog, otherwise we get infinite recursion
    //later on when we reassign clog's rdbuf.
    std::ostream clogCopy(std::clog.rdbuf());

    TeeDevice logTee(flog, clogCopy);
    TeeStream logTeeStream(logTee);

    logTeeStream << "This text gets clogged and flogged." << std::endl;

    //Modify clog to automatically go through the tee.
    std::streambuf *originalRdBuf = std::clog.rdbuf(logTeeStream.rdbuf());  

    std::clog << "This text doesn't only get clogged, it's flogged too." << std::endl;

    std::clog.rdbuf(originalRdBuf);
    std::clog << "This text avoids flogging." << std::endl;
}

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