Подтвердить что ты не робот

Перенаправление stdin и stdout из C

Я хочу снова открыть дескрипторы stdin и stdout (и, возможно, stderr в то время как я на нем), так что будущие вызовы printf() или putchar() или puts() перейдут к файл и будущие вызовы getc(), и это будет происходить из файла.

1) Я не хочу навсегда потерять стандартный ввод/вывод/ошибку. Я могу повторно использовать их позже в программе.

2) Я не хочу открывать новые дескрипторы файлов, потому что эти дескрипторы файлов должны быть переданы либо много, либо глобально (содрогание).

3) Я не хочу использовать любые open() или fork() или другие зависящие от системы функции, если я не могу помочь.

Итак, в основном, работает ли это:

stdin = fopen("newin", "r");

И, если это так, как я могу вернуть исходное значение stdin назад? Мне нужно сохранить его в FILE * и просто вернуть его позже?

4b9b3361

Ответ 1

Зачем использовать freopen()? Спецификация C89 имеет ответ в одной из концевых сносок для раздела <stdio.h>:

116. Основное использование функции freopen - это изменение файла, связанного со стандартом текстовый поток (stderr, stdin или stdout), поскольку эти идентификаторы не обязательно должны быть модифицируемые значения, значения которых возвращается функцией fopenможет быть назначено.

freopen обычно используется неправильно, например. stdin = freopen("newin", "r", stdin);. Это не более переносимо, чем fclose(stdin); stdin = fopen("newin", "r");. Оба выражения пытаются назначить stdin, которые не гарантируются назначением.

Правильный способ использования freopen состоит в том, чтобы опустить назначение: freopen("newin", "r", stdin);

Ответ 2

Я думаю, что вы ищете что-то вроде freopen()

Ответ 3

Это модифицированная версия метода Tim Post; Я использовал /dev/tty вместо/dev/stdout. Я не знаю, почему это не работает с stdout (который является ссылкой на /proc/self/fd/ 1):

freopen("log.txt","w",stdout);
...
...
freopen("/dev/tty","w",stdout);

Используя/dev/tty, вывод перенаправляется на терминал, с которого было запущено приложение.

Надеюсь, что эта информация полезна.

Ответ 4

Функция os dup2() должна обеспечивать то, что вам нужно (если не ссылки на то, что вам нужно).

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

Функция dup() дублирует дескриптор открытого файла. В частности, он предоставляет альтернативный интерфейс для службы, предоставляемой функцией fcntl(), с использованием значения константы команды F_DUPFD, а для третьего аргумента - 0. Двойной дублированный файловый дескриптор разделяет любые блокировки с оригиналом.

При успехе dup() возвращает новый файловый дескриптор, который имеет общее с оригиналом следующее:

  • Тот же открытый файл (или канал)
  • Указатель того же файла (оба файловых дескриптора используют один указатель файла)
  • Тот же режим доступа (чтение, запись или чтение/запись)

Ответ 5

freopen("/my/newstdin", "r", stdin);
freopen("/my/newstdout", "w", stdout);
freopen("/my/newstderr", "w", stderr);

... do your stuff

freopen("/dev/stdin", "r", stdin);
...
...

Это пикирует иглу на моем кругло-прямоугольном ящике-о-метре, что вы пытаетесь выполнить?

Edit:

Помните, что stdin, stdout и stderr являются файловыми дескрипторами 0, 1 и 2 для каждого вновь созданного процесса. freopen() должен поддерживать одни и те же fd, просто назначая им новые потоки.

Итак, хороший способ убедиться, что это на самом деле делать то, что вы хотите, будет:

printf("Stdout is descriptor %d\n", fileno(stdout));
freopen("/tmp/newstdout", "w", stdout);
printf("Stdout is now /tmp/newstdout and hopefully still fd %d\n",
   fileno(stdout));
freopen("/dev/stdout", "w", stdout);
printf("Now we put it back, hopefully its still fd %d\n",
   fileno(stdout));

Я считаю, что это ожидаемое поведение freopen(), как вы можете видеть, вы все еще используете только три дескриптора файлов (и связанные потоки).

Это переопределит любое перенаправление оболочки, поскольку для перенаправления оболочки ничего не будет. Тем не менее, вероятно, он сломает трубы. Возможно, вы захотите установить обработчик для SIGPIPE, если ваша программа окажется на заблокированном конце трубы (не FIFO, pipe).

Итак,./your_program --stdout/tmp/stdout.txt --stderr/tmp/stderr.txt должно быть легко выполнено с помощью функции freopen() и сохранения одинаковых фактических дескрипторов файлов. Я не понимаю, почему вам нужно будет вернуть их после их изменения? Разумеется, если кто-то передал какой-либо вариант, они хотели бы, чтобы он сохранялся до тех пор, пока программа не завершилась?

Ответ 6

freopen решает легкую часть. Сохранение старого stdin не сложно, если вы ничего не читали и хотите ли вы использовать системные вызовы POSIX, например, dup или dup2. Если вы начали читать, все ставки отключены.

Может быть, вы можете рассказать нам о контексте, в котором эта проблема возникает?

Я бы посоветовал вам придерживаться ситуаций, когда вы готовы отказаться от старых stdin и stdout и поэтому можете использовать freopen.

Ответ 7

А пока есть библиотека исходного кода C, которая сделает все это для вас, перенаправляя stdout или stderr. Но классная часть заключается в том, что она позволяет назначать столько функций обратного вызова, сколько вы хотите перехваченным потокам, что позволяет вам очень легко отправлять одно сообщение нескольким адресатам, БД, текстовому файлу и т.д.

Кроме того, тривиально создавать новые потоки, которые выглядят и ведут себя так же, как stdout и stderr, где вы также можете перенаправить эти новые потоки в несколько местоположений.

найдите библиотеку U-Streams C на * oogle.

Ответ 8

это самый доступный ручной и полезный способ

freopen("dir","r",stdin);