2013-08-06 7 views
6

Quello che voglio farereindirizzamento output/error al file sotto Unix C++ - ancora una volta

reindirizzamento stdout e stderr di uno o più file da dentro C++

Perché ne ho bisogno

Sto usando una libreria esterna di terze parti precompilata che produce una quantità ridicola di output, che vorrei reindirizzare su un file di log per mantenere pulita la console.

Condizioni

compatibilità non è un problema, il codice verrà eseguito solo su sistemi Unix. Il reindirizzamento non dovrebbe riguardare solo la stampa in stile C++ (std :: cout < < "ciao mondo" < < std :: endl), ma anche la stampa in stile c (printf ("ciao mondo \ n")).

Quello che ho provato finora

Sono stato navigando su StackOverflow per mezza giornata, la lettura di molteplici risposte alle persone che hanno problemi simili. Con l'aiuto di queste risposte, sono stato in grado di mettere insieme il seguente pezzo di codice:


#include <stdio.h> 
#include <iostream> 
#include <fcntl.h> 
#include "unistd.h" 

const int stdoutfd(dup(fileno(stdout))); 

int redirect_stdout(const char* fname){ 
    fflush(stdout); 
    int newstdout = open(fname, O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR | S_IRGRP |  S_IROTH); 
    dup2(newstdout, fileno(stdout)); 
    close(newstdout); 
} 

int restore_stdout(){ 
    fflush(stdout); 
    dup2(stdoutfd, fileno(stdout)); 
    close(stdoutfd); 
    return stdoutfd; 
} 

int main(){ 
    redirect_stdout("/dev/null"); 
    std::cout << "invisible 1" << std::endl; 
    restore_stdout(); 
    std::cout << "visible 1" << std::endl; 
    redirect_stdout("/dev/null"); 
    std::cout << "invisible 2" << std::endl; 
    restore_stdout(); 
    std::cout << "visible 2" << std::endl; 
    return 0; 
} 

Quello che mi sarei aspettato di vedere:

visible 1 
visible 2 

Quello che in realtà vedi

visible 1 

Cioè, quando si utilizza questo meccanismo per la prima volta, funziona - ma se usato di nuovo, il ripristino dell'output non funzionerà. Qualcuno può indicarmi cosa devo cambiare per far funzionare il meccanismo infinitamente spesso?

+0

Eventuali duplicati: http://stackoverflow.com/questions/4810516/c-redirecting-stdout – Kelm

risposta

4

Se si desidera poterlo riutilizzare, non chiudere stdoutfd in restore_stdout.

1

Siete alla ricerca di qualcosa di simile: -

int main() 
{ 
    // Save original std::cin, std::cout 
    std::streambuf *coutbuf = std::cout.rdbuf(); 
    std::streambuf *cinbuf = std::cin.rdbuf(); 

    std::ofstream out("outfile.txt"); 
    std::ifstream in("infile.txt"); 

    //Read from infile.txt using std::cin 
    std::cin.rdbuf(in.rdbuf()); 

    //Write to outfile.txt through std::cout 
    std::cout.rdbuf(out.rdbuf()); 

    std::string test; 
    std::cin >> test;   //from infile.txt 
    std::cout << test << " "; //to outfile.txt 

    //Restore back. 
    std::cin.rdbuf(cinbuf); 
    std::cout.rdbuf(coutbuf); 

} 

Dal mio precedente answer

+1

grazie per la risposta - tuttavia, avrei dichiarato che mi mancava per reindirizzare non solo C++ - istruzioni di stampa stile, ma anche istruzioni di stampa in chiaro con printf - il che, afaik, non porta a termine. scusa per l'imprecisione, ho modificato la domanda di conseguenza. – carsten

0

Per iostreams C++, è possibile utilizzare l'overload non-const di rdbuf per impostare std::cout ad un std::filebuf. (Questo è il metodo migliore per il tipo di una classe RAII, poiché è necessario ripristinarlo prima di lasciando principale.) Per C FILE*, è possibile utilizzare freopen, ma Non penso che sarà in grado di ripristinarlo.

FWIW: entrambe queste soluzioni utilizzano solo standard C++ o C, pertanto deve essere portatile.

1

bene i u'd migliore utilizzo freopen()

Usage Sintassi:

freopen("RedToFile","r",stdout); 
or 
freopen("/dev/null","a",stdout); 

lo stesso vale per "stderr"

0

Oltre a afr0ck risposta freopen() voglio dire che durante l'utilizzo di freopen() dovremmo stare attenti. Una volta che un flusso come stdout o stdin viene riaperto con l'assegnazione della nuova destinazione (qui il file 'output.txt') rimane sempre per un programma, a meno che non sia stato esplicitamente modificato.

freopen("output.txt", "a", stdout); 

Qui il flusso di output standard stdout viene riaperto e assegnato con il 'output.txt' di file. Successivamente, ogni volta che utilizziamo lo printf() o qualsiasi altro flusso stdout come - putchar(), ogni uscita andrà allo 'output.txt'. Per ottenere indietro il comportamento di default (che è la stampa l'output in console/terminale) di printf() o putchar() possiamo utilizzare la seguente riga di codice -

  • per gcc, distribuzione Linux come Ubuntu - freopen("/dev/tty", "w", stdout);
  • per Mingw C/C++, le finestre - freopen("CON", "w", stdout);

vedere il codice di esempio qui sotto -

#include <stdio.h> 

int main() { 

    printf("No#1. This line goes to terminal/console\n"); 

    freopen("output.txt", "a", stdout); 
    printf("No#2. This line goes to the \"output.txt\" file\n"); 
    printf("No#3. This line aslo goes to the \"output.txt\" file\n"); 

    freopen("/dev/tty", "w", stdout); /*for gcc, diffrent linux distro eg. - ubuntu*/ 
    //freopen("CON", "w", stdout); /*Mingw C++; Windows*/ 
    printf("No#4. This line again goes to terminal/console\n");   

} 

Questo il codice genera un file 'output.txt' nella directory corrente e i numeri n. 2 e n. 3 verranno stampati nel file 'output.txt'.

Grazie

Problemi correlati