2009-02-10 39 views
6

我想用這個段從Mr-Edd's iostreams article打印的std ::某處堵塞。重定向的std ::法院以定製寫入

#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 docs但我無法理解來做到這一點的最好辦法。我有一個顯示文本的方法,我只想用ostringstream中的任何數據調用它。

什麼是獲取發送到std ::東西堵塞重定向到我的選擇的方法最簡單/最好的方法是什麼?是如上述,並在同時填寫!EOF部分(不知道如何),或是否有更好的辦法,比方說通過重載一些地方「提交」操作者調用我的方法?我尋找熱塑成型的快速和容易的,我真的不想開始定義匯和用等輸入輸出流升壓的文章做 - 這東西是大大超過我的頭。

+0

你可以在你的問題是什麼更清楚了嗎? – 2009-02-10 16:39:21

回答

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; 
} 
+0

你的代碼段在一個空白項目中工作。我將你的水槽複製粘貼到我的真實項目中,並將你的main複製到某個init方法中,改變了NOTHING,並且我得到了幾頁增強廢話的錯誤。 – 2009-02-13 20:06:54

+0

(在這一行上:bio :: stream_buffer sb;) – 2009-02-13 20:07:51

7

認爲你想從ostream的拉文雖然它不是空的。你可以這樣做:

std::string s = oss.str(); 
if(!s.empty()) { 
    // output s here 
    oss.str(""); // set oss to contain the empty string 
} 

讓我知道這是不是你想要的。

當然,更好的解決方案是刪除中間人,並有一個新的streambuf去,無論你在哪裏真的想要它,以後不需要探測。像這樣(注意,這會爲每一個字符,但有足夠的緩衝選項的streambuf以及):

class outbuf : public std::streambuf { 
public: 
    outbuf() { 
     // no buffering, overflow on every char 
     setp(0, 0); 
    } 

    virtual int_type overflow(int_type c = traits_type::eof()) { 
     // add the char to wherever you want it, for example: 
     // DebugConsole.setText(DebugControl.text() + c); 
     return c; 
    } 
}; 

int main() { 
    // set std::cout to use my custom streambuf 
    outbuf ob; 
    std::streambuf *sb = std::cout.rdbuf(&ob); 

    // do some work here 

    // make sure to restore the original so we don't get a crash on close! 
    std::cout.rdbuf(sb); 
    return 0; 

}

+0

我沒有想到它會接近那麼簡單,但我會試一試。 – 2009-02-10 16:45:28

0

如果你只是想獲得ostringstream的內容,然後使用它的str()成員。例如:

string s = oss.str();  
4

我需要搶輸出到std ::從第三方庫的cout和std :: CERR和使用log4cxx記錄他們,仍保留原有產出。

這就是我想出來的。這是相當直接:

  • 我更換一個ostream(比如std ::法院)與我自己的類舊的緩衝區,這樣我可以訪問什麼都被寫入。

  • 我還使用舊的緩衝區創建了一個新的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; 
1

因爲你必須覆蓋溢出()和同步(),否則badbit首先之後始終將log4cxx例子流被接收。

請參見: 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; 
}