6

Mr-Eddのiostreams記事のこのスニペットを使用して、 std::clogをどこかに印刷したいと思います。

#include <iostream>
#include <iomanip>
#include <string>
#include <sstream>

int main()
{
    std::ostringstream oss;

    // Make clog use the buffer from oss
    std::streambuf *former_buff =
        std::clog.rdbuf(oss.rdbuf());

    std::clog << "This will appear in oss!" << std::flush;

    std::cout << oss.str() << '\\n';

    // Give clog back its previous buffer
    std::clog.rdbuf(former_buff);

    return 0;
}

だから、メインループで、私は次のようなことをします

while (! oss.eof())
{
    //add to window text somewhere
}

これがostringstreamのドキュメントですが、これを行うための最良の方法を理解するのに苦労しています。テキストを表示するメソッドがあります。ostringstream内の任意のデータを使用して呼び出したいだけです。

std :: clogに送信されたものを、選択したメソッドにリダイレクトするための最も簡単で最良の方法は何ですか?上記のように、while!eofの部分に入力しますか(方法はわかりません)、それとも、メソッドを呼び出す「commit」演算子をどこかにオーバーロードするなど、より良い方法がありますか?私はすばやく簡単なことを望んでいます。記事のようにブーストIOストリームを使用してシンクなどを定義し始めたくありません。

4

5 に答える 5

11

をご覧になることをお勧めしますBoost.IOStreams。それはあなたのユースケースにうまく適合しているようで、それを使用するのは驚くほど簡単です:

#include <boost/iostreams/concepts.hpp> 
#include <boost/iostreams/stream_buffer.hpp>
#include <iostream>

namespace bio = boost::iostreams;

class MySink : public bio::sink
{
public:
    std::streamsize write(const char* s, std::streamsize n)
    {
        //Do whatever you want with s
        //...
        return n;
    }
};

int main()
{
    bio::stream_buffer<MySink> sb;
    sb.open(MySink());
    std::streambuf * oldbuf = std::clog.rdbuf(&sb);
    std::clog << "hello, world" << std::endl;
    std::clog.rdbuf(oldbuf);
    return 0;
}
于 2009-02-10T18:34:11.520 に答える
4

サードパーティのライブラリから std::cout と std::cerr への出力を取得し、log4cxx を使用してログに記録し、元の出力を保持する必要がありました。

これが私が思いついたものです。それはかなり簡単です:

  • ostream の古いバッファ (std::cout など) を独自のクラスに置き換えて、これまでに書き込まれたものにアクセスできるようにします。

  • また、古いバッファーを使用して新しい std::ostream オブジェクトを作成し、ロガーに送信するだけでなく、引き続きコンソールに出力を取得できるようにします。これは便利だと思います。

コード:

class intercept_stream : public std::streambuf{
public:
    intercept_stream(std::ostream& stream, char const* logger):
      _logger(log4cxx::Logger::getLogger(logger)),
      _orgstream(stream),
      _newstream(NULL)
    {
        //Swap the the old buffer in ostream with this buffer.
        _orgbuf=_orgstream.rdbuf(this);
        //Create a new ostream that we set the old buffer in
        boost::scoped_ptr<std::ostream> os(new std::ostream(_orgbuf));
        _newstream.swap(os);
    }
    ~intercept_stream(){
        _orgstream.rdbuf(_orgbuf);//Restore old buffer
    }
protected:
    virtual streamsize xsputn(const char *msg, streamsize count){
        //Output to new stream with old buffer (to e.g. screen [std::cout])
        _newstream->write(msg, count);
        //Output to log4cxx logger
        std::string s(msg,count);
        if (_logger->isInfoEnabled()) {
            _logger->forcedLog(::log4cxx::Level::getInfo(), s, LOG4CXX_LOCATION); 
        }
        return count;
    }
private:
    log4cxx::LoggerPtr _logger;
    std::streambuf*    _orgbuf;
    std::ostream&      _orgstream;
    boost::scoped_ptr<std::ostream>  _newstream;
};

それを使用するには:

std::cout << "This will just go to my console"<<std::endl;
intercept_stream* intercepter = new intercept_stream(std::cout, "cout");
std::cout << "This will end up in both console and my log4cxx logfile, yay!" << std::endl;
于 2009-07-16T11:47:51.170 に答える
1

log4cxx の例では、overflow() と sync() をオーバーライドする必要があります。そうしないと、最初のストリームを受信した後に常に badbit が設定されます。

参照: http://groups.google.com/group/comp.lang.c++.moderated/browse_thread/thread/fd9d973282e0a402/a872eaedb142debc

InterceptStream::int_type InterceptStream::overflow(int_type c)
{
    if(!traits_type::eq_int_type(c, traits_type::eof()))
    {
        char_type const t = traits_type::to_char_type(c);
        this->xsputn(&t, 1);
    }
    return !traits_type::eof();
}

int InterceptStream::sync()
{
    return 0;
}
于 2011-01-04T19:57:38.680 に答える
0

ostringstream の内容を取得するだけの場合は、その str() メンバーを使用します。例えば:

string s = oss.str();    
于 2009-02-10T16:51:19.877 に答える