перенаправить stdout/stderr в файл под unix c++ - снова
что я хочу сделать
перенаправить stdout и stderr на один или несколько файлов из C++
зачем он мне нужен
Я использую внешнюю, предварительно скомпилированную стороннюю библиотеку, которая производит смешной объем вывода, который я хотел бы перенаправить в файл журнала, чтобы сохранить консоль чистой.
условия
совместимость не является проблемой, код будет работать только в системах Unix. Перенаправление должно влиять не только на печать в стиле c++(std::cout
то, что я пробовал до сих пор
Я просматривал 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
то есть при использовании этого механизма в первый раз он работает - но если используется снова, восстановление вывода не будет работать. Может ли кто-нибудь указать мне, что мне нужно изменить, чтобы механизм работал бесконечно часто?
5 ответов
Если вы хотите иметь возможность повторно использовать его, не закрывайте stdoutfd
на restore_stdout
.
ну я бы лучше использовать freopen()
Использование Синтаксис:
freopen("RedToFile","r",stdout);
or
freopen("/dev/null","a",stdout);
то же самое касается "stderr"
вы ищете что-то вроде этого :-
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);
}
из моего предыдущего ответ
кроме afr0ck ответ freopen() я хочу сказать, что при использовании freopen()
мы должны быть осторожны. Когда-то поток, как stdout
или stdin
возобновлено с назначением нового назначения(здесь '.txt' file) всегда остается для программы, если она не была явно изменена.
freopen("output.txt", "a", stdout);
здесь стандартный выходной поток stdout
возобновлено и назначено на '.txt'. После этого всякий раз, когда мы используем printf()
или любое другое stdout
поток, как - putchar()
тогда каждый вывод будет идти в '.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");
}
этот код генерирует '.txt' файл в вашем текущем каталоге и No#2 и No#3 будут напечатаны в '.txt'.
спасибо
для iostreams C++ вы можете использовать не-const перегрузку rdbuf
установить std::cout
до std::filebuf
. (Это лучше всего сделать
средство класса RAII, так как вы должны восстановить его раньше
покидаю мэйн.) Для C FILE*
, вы можете использовать freopen
, но
Не думаю, что вы сможете его восстановить.
FWIW: оба этих решения используют только стандартный C++ или C, поэтому должно быть портативным.