2013-08-06 8 views
6

Was ichUmleitung stdout/stderr unter Unix-C-Datei ++ - wieder

Umleitung stdout und stderr auf eine oder mehrere Dateien aus dem Inneren C++

Warum ich brauche es

tun wollen

Ich verwende eine externe, vorkompilierte Third-Party-Bibliothek, die eine lächerliche Menge an Ausgaben erzeugt, die ich in eine Protokolldatei umleiten möchte, um die Konsole sauber zu halten.

Bedingungen

Kompatibilität ist kein Problem, nur der Code auf Unix-Systemen laufen. Die Umleitung sollte nicht nur das C++ - Drucken beeinflussen (std :: cout < < "Hallo Welt" < < Std :: Endl), sondern auch c-style Drucken (printf ("Hallo Welt \ n")).

Was ich versucht habe bisher

ich auf Stackoverflow für einen halben Tag Surfen haben, mehrere Antworten auf Menschen mit ähnlichen Problemen zu lesen. Mit Hilfe dieser Antworten, konnte ich das folgende Stück Code zusammen:


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

Was ich erwarten würde, um zu sehen:

visible 1 
visible 2 

Was ich eigentlich siehe

visible 1 

Das heißt, wenn Sie dies verwenden Mechanismus zum ersten Mal, es funktioniert - aber wenn es erneut verwendet wird, wird die Wiederherstellung der Ausgabe nicht funktionieren. Kann mir jemand aufzeigen, was ich ändern muss, damit der Mechanismus unendlich oft funktioniert?

+0

Mögliche doppelt: http://stackoverflow.com/questions/4810516/c-redirecting-stdout – Kelm

Antwort

4

Wenn Sie es wiederverwenden möchten, schließen Sie nicht stdoutfd in restore_stdout.

1

Sind Sie für so etwas suchen: -

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); 

} 

Aus meiner früheren answer

+1

Dank für Ihre Antwort - aber soll ich gesagt hat, dass ich will nur die Umleitung nicht C++ - style print-Anweisungen, aber auch plain-c print-Anweisungen mit printf - was, afaik, Ihre Lösung nicht erreicht. Entschuldigung für die Ungenauigkeit, ich habe die Frage entsprechend bearbeitet. – carsten

0

Für C++ iostreams, können Sie die nicht konstante Überlastung von rdbuf verwenden std::cout auf einen std::filebuf einzustellen. (Dies wird am besten durch Mittel einer RAII-Klasse getan, da Sie es vor Haupt verlassen müssen.) Für C FILE* können Sie freopen verwenden, aber Ich glaube nicht, dass Sie in der Lage sein werden, es wiederherzustellen.

FWIW: Beide Lösungen verwenden nur Standard C++ oder C, daher sollte portabel sein.

1

gut u'd i bessere Nutzung freopen()

Verwendung Syntax:

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

das gleiche für "stderr"

0

Neben afr0ck Antwort von freopen() geht möchte ich sagen, dass wir bei der Verwendung von freopen() vorsichtig sein sollten. Sobald ein Stream wie stdout oder stdin mit der Zuweisung des neuen Ziels (hier die 'output.txt' Datei) wieder geöffnet wird, bleibt es immer für ein Programm, es sei denn, es wurde explizit geändert.

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

Hier die Standardausgabe stdout mit dem ‚output.txt‘ Datei wieder geöffnet und zugewiesen. Danach, wann immer wir printf() oder irgendeinen anderen stdout Strom wie - putchar() verwenden, dann geht jeder Ausgang zu der 'output.txt'. Um das Standardverhalten zurück (dh Drucken der Ausgabe in der Konsole/Terminal) von printf() oder putchar() wir die folgende Codezeile verwenden können -

  • für gcc, Linux-Distribution wie Ubuntu - freopen("/dev/tty", "w", stdout);
  • für Mingw C/C++, Fenster - freopen("CON", "w", stdout);

unter dem Codebeispiel See -

#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");   

} 

Diese code erzeugen Sie eine 'output.txt' Datei in Ihrem aktuellen Verzeichnis und die Nr. 2 und Nr. 3 werden in der Datei 'output.txt' gedruckt.

Dank