我正在尝试使用boost::iostreams output filter将字符串添加到流出的任何内容的开头和结尾。
我的代码可以使用,但只是第一次;第二次,输出似乎在某处丢失,写入方法似乎甚至没有被调用。我想起初我正在向流中发送一些触发其失败位的内容,但是流似乎很好。
在mac和linux上出现同样的问题,最新的boost release (1.48)和svn trunk,cout和文件接收器作为设备。
有没有人真正看过这部作品?那是一个错误吗?或者我在代码中做错了什么?
#include <iostream>
#include <sstream>
#include <boost/iostreams/concepts.hpp>
#include <boost/iostreams/device/file.hpp>
#include <boost/iostreams/filtering_stream.hpp>
#include <boost/iostreams/operations.hpp>
using std::cin;
using std::cout;
using std::endl;
using std::streamsize;
using std::string;
using std::stringstream;
class add_string_output_filter
: public boost::iostreams::multichar_output_filter
{
public:
template<typename Sink>
streamsize write(Sink& sink, const char* s, streamsize n)
{
string out_string = string(s);
// remove trailing '\0' to prevent line break
if (out_string[out_string.size()-1] == '\0')
out_string = out_string.substr(0, out_string.size()-1);
string pre_string("prepended string - ");
string app_string(" - appended string");
stringstream sstrm;
sstrm << pre_string << out_string << app_string << endl;
// TODO: char* to string, back to char* ?!?
return boost::iostreams::write(sink,
sstrm.str().c_str(),
sstrm.str().length());
}
};
int main()
{
boost::iostreams::filtering_ostream out;
out.push(add_string_output_filter());
out.push(cout);
// string #01 is printed,
// string #02 gets lost
out << "string #01" << endl;
out << "string #02" << endl;
}
答案 0 :(得分:0)
嗯,你的代码有很多问题,但我不确定
为什么没有输出第二个字符串。当我尝试代码时,你的
add_string_output_filter::write
只被调用一次(带有
"string #01\n"
);我希望每次缓冲区都会调用它
刷新(所以在第二次std::endl
之后第二次)。但即便如此
被称为第二次,我不认为输出是你所期望的
或想要。对于前缀和后缀行,您必须实际查看
在数据处,并正确处理'\n'
字符。这很多
使用简单的输出过滤器更简单:
class PrefixAndSuffixLineOutputFilter : public boost::iostreams::output_filter
{
bool isAtStartOfLine;
public:
PrefixAndSuffixLineOutputFilter() : isAtStartOfLine( true ) {}
template <typename Sink>
bool
put( Sink& dest, char ch )
{
static std::string const prefix( "prepending string - " );
static std::string const suffix( " - appended string" );
bool retval = true;
if ( isAtStartOfLine )
retval = boost::iostreams::write( dest, prefix.data(), prefix.size() ) == prefix.size();
if ( retval && ch == '\n' )
retval = boost::iostreams::write( dest, suffix.data(), suffix.size() ) == suffix.size();
if ( retval )
retval = boost::iostreams::put( dest, ch );
isAtStartOfLine = ch == '\n';
return retval;
}
};
通常,multichar_output_filter
是一种优化。如果你
阅读教程,最后,它说“请注意
写入的实现与您放置的内容非常相似
执行shell_comments_output_filter :: put里面的for
循环从0迭代到n。“这真的是关键:写
首先是简单的output_filter
,如果分析器显示的话
函数调用导致性能问题,切换到
multichar_output_filter
。 (并注意到你需要相同的状态
它,因为你必须正确输出前缀和后缀,无论在哪里
'\n'
出现在多字符缓冲区中。)
我可能会补充说isAtStartOfLine
状态在输出中非常频繁
过滤器。 (请注意,您不能在每次之后输出prefix
'\n'
,因为这将导致在...之后悬挂字符串"prefix"
最后'\n'
,并且在第一行开头没有"prefix"
。)我有
我自己的代码中的一个很好的例子,它在时间戳中插入了一个时间戳
每一行的开头,但Jonathan Turkanis没有包括这一点
他教程中的一个特例。