Как перенаправить стандартный вывод в файл, а затем восстановить стандартный вывод обратно?

Вот мой код, и я не могу заставить его работать.

int pfd = open("file", O_WRONLY, 0777);
int saved = dup(1);
close(1);
dup(pfd);
close(pfd);
printf("This goes into file\n");

// restore it back
dup2(saved, 1);
close(saved);
printf("this goes to stdout");

Я добавил некоторые изменения в свой код.


person posixKing    schedule 08.12.2017    source источник
comment
Однако dup(pfd); не заставит стандартный вывод записываться в файл.   -  person tkausl    schedule 08.12.2017
comment
Думали ли вы об использовании dup2 несколько раз?   -  person Basile Starynkevitch    schedule 08.12.2017
comment
Извините, я забыл добавить close(1) перед dup(pfd)   -  person posixKing    schedule 08.12.2017
comment
Но я открываю файл в самой первой строке. Решение по этой ссылке открывает его после дублирования. Как мне заставить свою работать?   -  person posixKing    schedule 08.12.2017
comment
@posixKing Открывает файл после дублирования stdin. На данный момент это два несвязанных файла. Какое значение может иметь порядок этих операций?   -  person bnaecker    schedule 08.12.2017


Ответы (1)


Вам нужно проверить возвращаемые значения ваших вызовов функций. Для большинства функций следует проверять наличие ошибок. Это могло выявить проблему, заключающуюся в том, что если вы хотите, чтобы open() создал запрошенный файл в том случае, если он изначально не существует, вам необходимо добавить флаг O_CREAT.

Но это не ваша главная проблема — вы имеете дело с проблемой буферизации. Вывод первого printf() буферизуется в памяти, поэтому, хотя файловый дескриптор 1 ссылается на ваш файл во время вызова printf(), данные, которые вы записываете, не сразу сбрасываются в целевой файл. Затем вы восстанавливаете исходный дескриптор файла stdout, поэтому, когда данные фактически сбрасываются, они переходят к (восстановленному) исходному стандартному выводу. Решите это с помощью fflush()ing перед переключением stdout обратно:

int pfd = open("file", O_WRONLY | O_CREAT, 0777);
int saved = dup(1);

close(1);
dup(pfd);
close(pfd);
printf("This goes into file\n");
fflush(stdout);  // <-- THIS

// restore it back
dup2(saved, 1);
close(saved);
printf("this goes to stdout");

Также обратите внимание, что dup2() чище и безопаснее для дублирования файлового дескриптора на конкретный номер файлового дескриптора. Вы делаете это при восстановлении, но вы также должны сделать это для первоначального перенаправления.

person John Bollinger    schedule 08.12.2017
comment
Плохо, это была ошибка с моей стороны. Отзовет комментарий. Спасибо за Ваш ответ. fflush делает свое дело - person posixKing; 08.12.2017