2012-02-13 69 views
0

我試圖用一個boost::iostreamsoutput filter將字符串添加到開始,無論我流出來的結束。升壓輸入輸出流: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

嗯,有很多事情你的代碼錯誤,但我不知道爲什麼 第二個字符串沒有被輸出。當我嘗試的代碼,你 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的實現放入 循環中從0到n的迭代。 」這確實是關鍵:首先編寫 簡單output_filter,如果分析器顯示 函數調用導致性能問題,請切換到 multichar_output_filter。 (請注意,你需要同樣的狀態 它,因爲你必須輸出前綴和後綴正確無論在哪裏發生在多字符緩衝區 的'\n'的。)

我想補充的是,isAtStartOfLine狀態在輸出 過濾器中頻率非常高。 (請注意,你不能簡單地輸出prefix'\n'後,因爲這將導致懸掛串"prefix"的 最終'\n'後,並沒有"prefix"在第一線的開始。)我在 的一個很好的例子我自己的代碼,它在每行的開頭都插入了一個時間戳,但是Jonathan Turkanis在他的教程中沒有包含這個特定的例子。