2014-03-01 3 views
5

Ich habe den folgenden Code, der meine std::cout Ausgabe in eine Protokolldatei umleitet.Hinzufügen Zeitstempel mit 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! 

Nun, was ich will, ist, dass, wenn ein Zeilenumbruch auftritt, dann wird der aktuelle Zeitstempel wird in die Datei geschrieben werden.

Ich weiß, dass ich diese achive mit:

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

Aber was ich will, ist, dass die std::cout davon automatisch irgendwie zu kümmern. Ist das möglich?

+0

Sie sollten in Erwägung ziehen, Ihren eigenen 'std :: streambuf' für z. eine "std :: ostream" -konforme Logger-Klassenimplementierung, um dies zu erreichen. –

+2

Ohne ein open-ended streambuf zu implementieren, das die Ausgabe ansammelt und bei jedem Flush einen Timestamp rackst, zögere ich vorsichtig zu sagen, dass dies auf eine andere Weise möglich ist. Die Iostream-Leute sind dafür bekannt, Kaninchen aus den seltsamsten Orten zu ziehen, also sag niemals nie, aber wenn ich weiß, was ich von ihnen weiß, sehe ich es wahrscheinlich nicht anders. – WhozCraig

+0

In Anbetracht der Tatsache, dass Sie neu in C++ sind und die gegebenen Antworten auf ziemlich fortgeschrittene Manipulation des IO-Prozesses beruhen, werde ich Ihnen empfehlen, entweder die Antwort von Paul Evans zu verwenden oder aufzugeben. – elyashiv

Antwort

9

Ich nehme an, dass Sie den TimeStamp drucken möchten, wenn das erste Zeichen der nächsten Zeile in der Ausgabe erscheint. Nimm eine neue Klasse und vererbe sie von std :: streambuf und verbinde sie auf die gleiche Weise wie mit dem Filebuf. Wenn ein Newline-Charater erscheint, speichern Sie dieses Ereignis im Objekt. Erscheint ein anderes Zeichen, fügen Sie dem Stream den Zeitstempel hinzu.

Ich schrieb ein Beispiel, das das RAII-Idiom zum Verbinden des Streambuf verwendet.

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_; 
}; 

Anruf ein Objekt dieser Klasse in folgenden Weise:

// 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, Danke.Wie Codierung wie Sie tun. Ich weiß, dass es nicht durch einen Tag erreicht werden kann. Wie kann ich wie du sein? – Sigstop

+0

wenn Codierung zu Sucht wird ;-) –

+0

Ich mache eine kleine Änderung im Code auch Leistung zu erhöhen und den Stringstream zu beseitigen –

0

Sie wollen so etwas wie:

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

und es wie folgt verwendet werden:

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

Er will 'std :: cout << something-here ', um einen Zeitstempel transparent voranzustellen. I.e. Überall wird 'std :: cout' verwendet, wird nicht nur auf die Ziel-Ausgabedatei umgeleitet, sondern erhält für jede geschriebene Zeile Timestamp-Präambeln, ohne die Seite * caller * zu ändern. – WhozCraig

+1

@Evans, ich will das nicht.Ich werde std :: cout << "Druckdaten" << std :: endl. Dadurch werden die Daten automatisch mit Zeitstempel gedruckt. – Sigstop

+0

Wenn Sie schon da sind, um eine zusätzliche Funktion zu bieten, sollten Sie es zu einem allgemeinen 'std :: ostream'-Manipulator machen! –

0

versuchen so etwas wie die folgenden (es ist nur eine abstrakte, ich habe es nicht getestet):

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

Bitte testen Sie es und lassen Sie es mich wissen. Ich bin neu in C++ – Sigstop

2

Das ist ein Hack von einem anderen Punkt.

Wenn Sie das Programm ausführen, leiten Sie die Ausgabe in awk und fügen Sie dort den Zeitstempel hinzu. Der Befehl:

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

Wenn Sie Windows verwenden, können Sie glotzen von this website herunterladen.

Sie können die von strftime gedruckte Uhrzeit formatieren. Weitere Daten dazu finden Sie unter in the manual

+0

aufgerufen ja Mann dies ist auch möglich. Folge den Anweisungen von cpp-prog. – Sigstop