Вывод в файл и командную строку - PullRequest
0 голосов
/ 09 июля 2010

Я прочитал о freopen, чтобы перенаправить все printf в файл, но мне бы хотелось, чтобы вывод выводился на экран. Есть ли простой способ перенаправить printfs в файл и получить вывод строки cmd?

Спасибо!

Ответы [ 3 ]

1 голос
/ 09 июля 2010

Другая альтернатива - написать функцию, которая работает как printf, но направляет вывод в два разных места. Например:

#include <stdio.h>
#include <stdarg.h>

void printf2(FILE *fp, char *format, ...)
{
    va_list ap;
    va_list ap2;

    va_start(ap, format);
    va_copy(ap2, ap);

    vfprintf(fp, format, ap);
    va_end(ap);

    vprintf(format, ap2);
    va_end(ap2);
}

Затем вы можете вызвать printf2 так же, как вы бы позвонили fprintf, и вывод будет идти как к переданному указателю FILE, так и к stdout:

FILE *fp = fopen("/tmp/foo", "w");
printf2(fp, "This is a test.\n");

Этот подход не использует подпроцессы или каналы, и при необходимости его можно обобщить для нескольких файловых указателей.

0 голосов
/ 09 июля 2010

freopen не очень хорошая идея для перенаправления стандартного вывода. Он не обязательно будет использовать один и тот же номер дескриптора файла, поэтому дочерние процессы могут не наследовать новый стандартный вывод (или могут вообще не получить стандартный вывод). Лучше использовать open, а затем dup2 или close(0), а затем open, чтобы создать новую цель для stdout.

0 голосов
/ 09 июля 2010

Из-за пределов программы, используйте "tee":

# echo foo | tee foo.txt
foo
# cat foo.txt
foo

На самом деле, вы можете открыть () канал для тройника, который записывает файл, хотя это сильно загружает систему.Что-то на этот счет:

FILE *stream_to_write_to = popen( "tee filename.txt" );
fprintf( stream_to_write_to, "goes to filename.txt and stdout\n" );

Мне любопытно посмотреть, есть ли быстрый способ сделать это из-C, потому что на каком-то уровне это предполагает копирование данных.Легко получить два файловых дескриптора для записи в одно и то же место, используя dup () или тому подобное, но обратная сторона более сложна.Это может включать вставку модуля (общий пример - «connld» в поток), хотя, честно говоря, я никогда не видел, чтобы он использовался, поэтому я бы хотел увидеть сам пример рабочего кода.

Лучшая ссылкаЯ могу дать «Расширенное программирование в среде UNIX» Стивенса.

Обновление:

Чтобы поговорить с комментарием R ниже, вышеприведенное решение является несколько более тяжелой версией просто fork / exec-перенаправление ручки ребенка в другое место.И то и другое решит проблему, хотя я предпочитаю вышесказанное, потому что его легче очистить, но, честно говоря, оба решения довольно тяжелые.Fork () не является легкой функцией.Если суть вопроса в том, чтобы сделать это без fork / exec, то я не уверен, я бы тоже хотел знать.Если с fork / exec все в порядке, то использование его напрямую или popen () приведет к его взлому.

...