2014-03-01 29 views
5

我有以下代碼將我的std::cout輸出重定向到日誌文件。添加時間戳與std :: cout

std::ofstream out("out.txt"); 
std::streambuf *coutbuf = std::cout.rdbuf(); //save old buf 
std::cout.rdbuf(out.rdbuf()); //redirect std::cout to out.txt! 

現在我想的是,每當一個新行出現,那麼當前時間戳將被寫入該文件。

我知道我能實現這一目標:

std::cout << getTime() << "printing data" << std::endl; 

但我想是的std::cout照顧它會自動莫名其妙。那可能嗎?

+0

你應該考慮爲例如自己的'std :: streambuf'提供自己的'std :: streambuf'。符合'std :: ostream'的記錄器類實現來實現這一點。 –

+2

如果沒有實現一個開放式的streambuf來積累輸出,並在每次刷新時先插入一個時間戳,我會謹慎地猶豫,說這可能是另一種方式。 iostream傢伙知道把兔子從最奇怪的地方拉出來,所以永遠不要說永遠,但知道我所知道的他們,我不認爲它可能是另一種方式。 – WhozCraig

+0

考慮到你對C++是陌生的,並且給出的答案依賴於IO過程的相當先進的操作,我會推薦你​​使用Paul Evans的答案,或者放棄它。 – elyashiv

回答

9

我假設,如果下一行的第一個字符出現在輸出中,您希望打印TimeStamp。 接受一個新類並從std :: streambuf繼承它,並以與filebuf相同的方式連接它。如果出現換行符,則將該事件存儲在對象中。出現另一個字符將時間戳添加到流中。

我寫了一個使用RAII語言來連接streambuf的例子。

class AddTimeStamp : public std::streambuf 
{ 
public: 
    AddTimeStamp(std::basic_ios<char>& out) 
     : out_(out) 
     , sink_() 
     , newline_(true) 
    { 
     sink_ = out_.rdbuf(this); 
     assert(sink_); 
    } 
    ~AddTimeStamp() 
    { 
     out_.rdbuf(sink_); 
    } 
protected: 
    int_type overflow(int_type m = traits_type::eof()) 
    { 
     if(traits_type::eq_int_type(m, traits_type::eof())) 
      return sink_->pubsync() == -1 ? m: traits_type::not_eof(m); 
     if(newline_) 
     { // -- add timestamp here 
      std::ostream str(sink_); 
      if(!(str << getTime())) // add perhaps a seperator " " 
       return traits_type::eof(); // Error 
     } 
     newline_ = traits_type::to_char_type(m) == '\n'; 
     return sink_->sputc(m); 
    } 
private: 
    AddTimeStamp(const AddTimeStamp&); 
    AddTimeStamp& operator=(const AddTimeStamp&); // not copyable 
    // -- Members 
    std::basic_ios<char>& out_; 
    std::streambuf* sink_; 
    bool newline_; 
}; 

呼叫以下方式這個類的一個對象:

// some initialisation .. 
{ 
    AddTimeStamp ats(cout); // timestamp is active 
    // every output to 'cout' will start with a 'getTime()' now 
    // ... 
} // restore the old streambuf in the destructor of AddTimeStamp 
+1

@ cpp-proger,謝謝。如何編碼像你一樣。我知道這是一天無法實現的。我怎麼能像你一樣? – Sigstop

+0

當編碼變得成癮時;-) –

+0

我在代碼中做了一些改動,提高了性能並消除了stringstream –

0

你想要的東西,如:

ostream & addTime() { 
    std::cout << getTime(); 
    return std::cout; 

,並使用它像這樣:

addTime() << "printing data" << std::endl; 
+1

他希望'std :: cout << something-here'透明地預先加上一個時間戳。即使用'std :: cout'的每個地方不僅被重定向到目標輸出文件,而且每一行寫入時間戳前導都不會改變*調用者端。 – WhozCraig

+1

@Evans,我不想那樣。我將使用std :: cout <<「打印數據」<< std :: endl。這將自動打印帶時間戳的數據。 – Sigstop

+0

如果你已經在那裏提供一個額外的功能,你應該使它成爲一個通用的'std :: ostream'操縱器! –

0

嘗試像以下(這只是一個抽象的,我沒有測試):

class logger : ostream 
{ 
    bool line = true; 
public: 
    template<typename T> ostream& operator<< (T somedata) 
    { 
     if (line) 
      ostream << getTime(); 
     ostream << somedata; 
     line = somedata == std::endl; 
    } 
} 
+0

PLease測試它並讓我知道。我是新的C++ – Sigstop

2

這是從不同角度黑客攻擊。

運行該程序時,將輸出管道輸入awk,並在其中添加時間戳。命令:

<program> | awk '{print strftime()" "$0}' > logfile 

如果您使用的是Windows,您可以從this website下載gawk。

您可以格式化由strftime打印的時間。關於這方面的更多數據可以參考in the manual

+0

是的,這個也是可以的。按照cpp-prog的回答。 – Sigstop