2012-02-13 7 views
0

私がストリームアウトするものの先頭と末尾に文字列を追加するのに、boost::iostreamsoutput filterを使用しようとしています。boost iostreams:output_filterは一度だけ動作します

以下のコードは動作しますが、初めてです。 2回目は、出力がどこかで失われているように見えますが、書き込みメソッドは呼び出されないようです。私は最初にストリームに何かを送って失敗ビットをトリガーすると思ったが、ストリームは良さそうだ。

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

まあ、そこにあなたのコードが間違って多くのものがありますが、2番目の文字列が出力されていない理由を私は わかりません。コードを試してみると、 add_string_output_filter::writeは一度だけ呼び出されます( "string #01\n")。私はバッファが がフラッシュされるたびに呼び出されると期待しています(2回目の後に2回目のstd::endl)。しかし、たとえ が2回目に呼ばれたとしても、出力が期待通りではないと私は思っていません。 接頭辞と接尾辞の行については、実際には とデータを照らし、'\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の実装に入れた場合と非常によく似ています。 のループを0からn 。 ”これは実際にキーです。最初に をoutput_filterと書いて、 ファンクションコールによってパフォーマンスの問題が発生していることを示す場合は multichar_output_filterに切り替えてください。 (そして、あなたが正しくかかわらず '\n'は複数文字バッファに発生した場所の出力に接頭辞と接尾辞を持っていますので、あなたは、 でそれを同じ状態を必要とするだろうことに注意してください。)

私がいることをisAtStartOfLine状態を追加することができますフィルタ出力では非常に頻繁です。 フィルタ。 (つまり、最初の行の先頭に 最終'\n'後のぶら下がり文字列"prefix"、ノー"prefix"になりますから、'\n' すべての後prefixつまりあなたは、単に出力することはできません。)私は私の中でこの 良い例を持っていました独自のコードで、各行の先頭に のタイムスタンプを挿入しましたが、Jonathan Turkanisはこのチュートリアルの 特定の例を含めませんでした。

関連する問題