[英]redirect std::cout to a custom writer
I want to use this snippet from Mr-Edd's iostreams article to print std::clog somewhere. 我想使用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;
}
so, in a mainloop, I will do something like 所以,在一个主循环中,我会做类似的事情
while (! oss.eof())
{
//add to window text somewhere
}
Here's the ostringstream docs but I'm having trouble understanding the best way to do this. 这是ostringstream文档,但我无法理解这样做的最佳方法。 I have a method that displays the text, I just want to call it with any data in the ostringstream.
我有一个显示文本的方法,我只想用ostringstream中的任何数据调用它。
What is the easiest/best way to get anything sent to std::clog redirected to a method of my choice? 将发送到std :: clog的任何内容重定向到我选择的方法的最简单/最好的方法是什么? is it as above, and fill in the while !eof part (not sure how), or is there a better way, say by overloading some 'commit' operator somewhere that calls my method?
它是如上所述,并填写while!eof部分(不确定如何),或者是否有更好的方法,比如通过在调用我的方法的地方重载一些'commit'运算符? I'm loking for quick and easy, I really don't want to start defining sinks and such with boost iostreams as the article does - that stuff is way over my head.
我喜欢快速简单,我真的不想开始定义接收器,就像文章那样使用boost iostreams - 这些东西已经超出了我的想象。
I encourage you to look at Boost.IOStreams
. 我鼓励你看看
Boost.IOStreams
。 It seems to fit your use-case nicely, and using it is surprisingly simple: 它似乎很适合您的用例,使用它非常简单:
#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;
}
I think you want to pull the text from the ostream while it's not empty. 我想你想从ostream中取出文本而不是空的。 You could do something like this:
你可以这样做:
std::string s = oss.str();
if(!s.empty()) {
// output s here
oss.str(""); // set oss to contain the empty string
}
Let me know if this isn't what you wanted. 如果这不是您想要的,请告诉我。
Of course, the better solution is to remove the middle man and have a new streambuf go wherever you really want it, no need to probe later. 当然,更好的解决方案是移除中间人,并在你真正想要的地方有一个新的streambuf,无需稍后进行探测。 something like this (note, this does it for every char, but there is plenty of buffering options in streambufs as well):
这样的事情(注意,这适用于每个char,但streambufs中还有很多缓冲选项):
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;
} }
I needed to grab outputs to std::cout and std::cerr from third party libraries and log them using log4cxx, and still retaining the original outputs. 我需要从第三方库中获取std :: cout和std :: cerr的输出,并使用log4cxx记录它们,并仍然保留原始输出。
This is what I came up with. 这就是我提出的。 It's pretty straight-forward:
这非常简单:
I replace the old buffer of an ostream (like std::cout) with my own class so that I get access to what ever is written to it. 我用自己的类替换了ostream的旧缓冲区(比如std :: cout),以便我可以访问写入它的内容。
I also create a new std::ostream object with the old buffer so that I can continue to get the output to my console, besides sending it to my logger. 我还使用旧缓冲区创建一个新的std :: ostream对象,这样我就可以继续将输出发送到我的控制台,除了将它发送到我的记录器。 Which I find kind of handy.
我觉得哪种方便。
Code: 码:
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;
};
Then to use it: 然后使用它:
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;
For the log4cxx example you must override overflow() and sync() otherwise the badbit is always set after first stream is received. 对于log4cxx示例,您必须覆盖overflow()和sync(),否则在收到第一个流后始终设置badbit。
See: http://groups.google.com/group/comp.lang.c++.moderated/browse_thread/thread/fd9d973282e0a402/a872eaedb142debc 请参阅: 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;
}
If you just want to get the contents of the ostringstream, then use its str() member. 如果您只想获取ostringstream的内容,请使用其str()成员。 For example:
例如:
string s = oss.str();
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.