2014-11-30 42 views
5

Piszę kod, w którym muszę wydrukować te same dane na konsoli i do pliku. Czy istnieje sposób wypełnienia wspólnego obiektu strumienia wyjściowego, a następnie wyświetlenia go na konsoli przy użyciu cout i wyeksportowania go do pliku przy użyciu bibliotek fstream i iostream?Czy istnieje sposób utworzenia wspólnego obiektu strumienia wyjściowego do wydrukowania na konsoli i do pliku w języku C++?

+3

Użyj [ 'boost :: iostreams :: tee_device'] (http://www.boost.org/doc/libs/ 1_39_0/libs/iostreams/doc/functions/tee.html). – 0x499602D2

+0

Polecam zrobić to w środowisku wywołującym. –

Odpowiedz

6

Pewnie. Po prostu utworzysz odpowiedni bufor strumienia, który prawdopodobnie przechowuje do innych buforów strumieniowych, które zapisuje wewnętrznie. Używając tego bufora strumieniowego, utworzysz std::ostream do którego piszesz.

Na przykład, tutaj jest prosta realizacja tego podejścia:

#include <streambuf> 
#include <ostream> 

class teebuf 
    : public std::streambuf 
{ 
    std::streambuf* sb1_; 
    std::streambuf* sb2_; 

    int overflow(int c) { 
     typedef std::streambuf::traits_type traits; 
     bool rc(true); 
     if (!traits::eq_int_type(traits::eof(), c)) { 
      traits::eq_int_type(this->sb1_->sputc(c), traits::eof()) 
       && (rc = false); 
      traits::eq_int_type(this->sb2_->sputc(c), traits::eof()) 
       && (rc = false); 
     } 
     return rc? traits::not_eof(c): traits::eof(); 
    } 
    int sync() { 
     bool rc(false); 
     this->sb1_->pubsync() != -1 || (rc = false); 
     this->sb2_->pubsync() != -1 || (rc = false); 
     return rc? -1: 0; 
    } 
public: 
    teebuf(std::streambuf* sb1, std::streambuf* sb2) 
     : sb1_(sb1), sb2_(sb2) { 
    } 
}; 

class oteestream 
    : private virtual teebuf 
    , public std::ostream { 
public: 
    oteestream(std::ostream& out1, std::ostream& out2) 
     : teebuf(out1.rdbuf(), out2.rdbuf()) 
     , std::ostream(this) { 
     this->init(this); 
    } 
}; 

#include <fstream> 
#include <iostream> 

int main() 
{ 
    std::ofstream fout("tee.txt"); 
    oteestream tee(fout, std::cout); 
    tee << "hello, world!\n"; 
} 
+1

Niestandardowy bufor strumienia może być tu jednak przesadzony. Zapisywanie do 'stringstream' i wysyłanie tego dwa razy może być wystarczająco dobre. W każdym razie, dobrze. (BTW: Miałeś ten kod leżący w pobliżu?) – Deduplicator

+1

@Deduplicator: tak, istnieje rozwiązanie, które jest PITA do użycia i odpowiednie rozwiązanie, które jest przyjemne w użyciu. Zawijanie bufora strumienia do 'std :: ostream' sprawia, że ​​bufor strumienia tee jest całkiem przyjemny w użyciu. ... i, tak, miałem ten kod leżący: nie piszę tego szybko :-) –