перенаправить stdout / stderr в файл под Unix снова

Что я хочу сделать

перенаправить stdout и stderr на один или несколько файлов изнутри c ++

Зачем мне это нужно

Я использую внешнюю, предварительно скомпилированную стороннюю библиотеку, которая производит смехотворное количество выходных данных, которые я хотел бы перенаправить в файл журнала, чтобы сохранить консоль в чистоте.

условия

Совместимость не является проблемой, код будет работать только на системах Unix. Перенаправление должно влиять не только на печать в стиле c ++ (std :: cout << «Привет, мир» << std :: endl), но также и печать в стиле c (printf («hello world \ n»)).

Что я пробовал до сих пор

Я полдня просматривал stackoverflow, читая несколько ответов для людей, имеющих схожие проблемы. С помощью этих ответов я смог собрать следующий фрагмент кода:


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

Что бы я ожидал увидеть:

visible 1
visible 2

Что я на самом деле вижу

visible 1

То есть при первом использовании этого механизма он работает, но при повторном использовании восстановление выходных данных работать не будет.
Может кто-нибудь указать мне, что мне нужно изменить, чтобы механизм работал бесконечно часто?

7

Решение

Если вы хотите использовать его повторно, не закрывайте stdoutfd в restore_stdout,

4

Другие решения

ну, я бы лучше использовать freopen ()

Синтаксис использования:

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

то же самое касается «stderr»

2

Вы ищете что-то вроде этого: —

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

}

Из моего ранее ответ

1

В дополнение к afr0ck ответ freopen () Я хочу сказать, что при использовании freopen() мы должны быть осторожны Однажды поток как stdout или же stdin открывается с назначением нового пункта назначения (здесь ‘Output.txt’ файл) всегда остается для программы, если она не была явно изменена.

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

Здесь стандартный поток вывода stdout вновь открывается и назначается с ‘Output.txt’ файл. После этого всякий раз, когда мы используем printf() или любой другой stdout поток как — putchar() тогда каждый вывод будет идти к ‘Output.txt’. Чтобы вернуть поведение по умолчанию (то есть вывод на консоль / терминал) printf() или же putchar() мы можем использовать следующую строку кода —

  • для gcc, дистрибутив Linux, как Ubuntu — freopen("/dev/tty", "w", stdout);
  • для Mingw C / C ++, windows — freopen("CON", "w", stdout);

Смотрите пример кода ниже —

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

}

Этот код генерирует ‘Output.txt’ файл в вашем текущем каталоге и № 2 и № 3 будут напечатаны в ‘Output.txt’ файл.

Спасибо

1

Для C ++ iostreams вы можете использовать неконстантную перегрузку rdbuf
установить std::cout к std::filebuf, (Это лучше всего сделать
означает класс RAII, так как вы должны восстановить его до
оставляя главное.) Для С FILE*, ты можешь использовать freopen, но
Я не думаю, что вы сможете восстановить его.

FWIW: оба эти решения используют только стандартные C ++ или C, поэтому
должен быть портативным

0
По вопросам рекламы [email protected]