boost iostreams:output_filter只能工作一次

时间:2012-02-13 06:37:49

标签: c++ boost filter boost-iostreams

我正在尝试使用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;
}

1 个答案:

答案 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没有包括这一点 他教程中的一个特例。