【问题标题】:boost iostreams: output_filter works only onceboost iostreams: output_filter 只工作一次
【发布时间】:2012-02-13 06:37:49
【问题描述】:

我正在尝试使用 boost::iostreams output filter 在我流出的任何内容的开头和结尾添加一个字符串。

我下面的代码有效,但只是第一次;第二次,输出似乎在某处丢失,甚至似乎没有调用 write 方法。起初我以为我正在向触发其失败位的流发送一些东西,但流看起来不错。

同样的问题出现在 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;
}

【问题讨论】:

    标签: c++ boost filter boost-iostreams


    【解决方案1】:

    嗯,您的代码有很多问题,但我不确定 为什么没有输出第二个字符串。当我尝试代码时,您的 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 是一种优化。如果你 阅读教程,最后,它说“注意 write 的实现与您将得到的非常相似 shell_cmets_output_filter::put 在 for 中的实现 循环从 0 迭代到 n。”这真的是关键:写 首先是简单的output_filter,如果分析器显示 函数调用导致性能问题,切换到 multichar_output_filter。 (请注意,您需要相同的状态 它,因为无论在哪里,您都必须正确输出前缀和后缀 '\n' 出现在多字符缓冲区中。)

    我可能会补充一点,isAtStartOfLine 状态在输出中非常频繁 过滤器。 (请注意,您不能简单地输出 prefix 在每个 '\n',因为这将导致一个悬空字符串 "prefix" 在 最后'\n',第一行开头没有"prefix"。)我有 我自己的代码中的一个很好的例子,它在 每行的开头,但 Jonathan Turkanis 没有包括这个 他的教程中的特定示例。

    【讨论】:

      猜你喜欢
      • 2019-12-20
      • 1970-01-01
      • 2012-11-11
      • 2010-10-14
      • 2012-06-06
      • 2017-01-06
      • 2018-06-22
      • 2015-09-18
      • 2013-12-31
      相关资源
      最近更新 更多