オリジナルの詰まりやログファイルにティーして目詰まりを再定義するには?
質問
私はここに便利なスタートを見ます:
http://www.cs.technion.ac。 IL /〜imaman /プログラム/ teestream.htmlする
そして、それが目詰まりし、ログファイルの両方に行く新しい流れを作るために素晴らしい作品ます。
しかし、私は次のように影響を与えないように、新しい流れが詰まりと同じRDBUF()を持っているので、それが動作しない新しいストリームであることを目詰まりを再定義しようとした場合:
clog.rdbuf(myTee.rdbuf());
それでは、どのように私は、目詰まりのターゲットにすることができ、独自のRDBUFを()持っているティークラスを変更することができますか?
感謝します。
-William
解決
::代わりに別のストリームに出力を送るのティーのために詰まらせるには、1つの下のレベルに作業する必要があります。その代わりのostreamから派生するの、ストリームバッファから派生します。そして、あなたがこれを行うことができます:
fstream logFile(...);
TeeBuf tbuf(logFile.rdbuf(), clog.rdbuf());
clog.rdbuf(&tbuf);
あなた自身のストリームバッファクラスを派生する方法の詳細については、<のhref =「http://www2.roguewave.com/support/docs/sourcepro/edition9/html/stdlibug/39-2.html」のrelを参照してください= "nofollowをnoreferrer">ここを。
他のヒント
あなたは「ティー」はRDBUFレベルで動作していないので、やろうとしyour've何を行うにはしたくありません。だから、何か他のものにRDBUFが動作しません設定、出力が1つのストリームのみになります。
あなたがそこに例を実行する必要があります:
例えばます。
fstream clog_file(...);
xstream clog_x(...);
TeeStream clog(clog_file, clog_x);
、代わりに元の詰まりのどこにでも詰まりを使用します。
ここで仕事をしているようだ、私が作成したクラスは、手伝っすべての人に感謝です!
-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;
};
私はちょうどそれを行うにはブーストのiostreamのものを使用することになります。
#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;
}