Я попробовал вашу конфигурацию на виртуальной машине F29. Вот что я сделал:
Надеюсь, это поможет
Я поощряю Вас смотреть на 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;
}
Если Вы просто хотите получить содержание ostringstream, то используйте его ул. () участник. Например:
string s = oss.str();
Я думаю, что Вы хотите вытянуть текст от ostream, в то время как это не пусто. Вы могли сделать что-то вроде этого:
std::string s = oss.str();
if(!s.empty()) {
// output s here
oss.str(""); // set oss to contain the empty string
}
Сообщите мне, не является ли это тем, что Вы хотели.
Конечно, лучшее решение состоит в том, чтобы удалить среднего человека и иметь новый streambuf, идут везде, где Вы действительно хотите его, никакая потребность зондировать позже. что-то вроде этого (примечание, это делает это для каждого символа, но существует много буферизации опций в 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;
}
Мне нужно было получить выходные данные в 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;