Как переопределить сабо, чтобы перейти к оригинальному сабо и лог-файлу? - PullRequest
4 голосов
/ 02 июня 2009

Я увидел здесь полезное начало:

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

И это прекрасно работает для создания нового потока, который идет как в засорение, так и в файл журнала.

Однако, если я попытаюсь переопределить clog, чтобы он стал новым потоком, он не будет работать, потому что новый поток имеет ту же функцию rdbuf (), что и clog, поэтому следующее не даст эффекта:

clog.rdbuf(myTee.rdbuf());

Так как же я могу изменить класс tee, чтобы он имел собственный rdbuf (), который затем может быть целью clog?

Спасибо.

-William

Ответы [ 4 ]

3 голосов
/ 03 июня 2009

Если вы действительно хотите продолжать использовать std :: clog для тройника вместо отправки вывода в другой поток, вам нужно работать на один уровень ниже: вместо того, чтобы выводиться из ostream, наследовать от streambuf. Тогда вы можете сделать это:

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

Для получения дополнительной информации о том, как получить собственный класс streambuf, см. здесь .

2 голосов
/ 02 июня 2009

Вы не хотите делать то, что пытались сделать, потому что «ти» не работает на уровне rdbuf. Так что установка rdbuf на что-то другое не будет работать, вывод будет идти только в один поток.

Вам нужно следовать примеру:

, например

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

тогда везде используйте clog вместо исходного.

1 голос
/ 14 июня 2009

Я бы просто использовал материал Boost iostreams, чтобы сделать это.

<code>#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;
}

1 голос
/ 04 июня 2009

Вот класс, который я создал, который, кажется, делает свою работу, спасибо всем, кто помог!

-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;

};
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...