我读到freopen
将所有内容重定向printf
到一个文件,但我也希望将输出打印在屏幕上。有没有一种简单的方法可以将 printfs 重定向到文件并获取 cmd 行输出?
谢谢!
另一种选择是编写一个类似 的函数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
指针和标准输出:
FILE *fp = fopen("/tmp/foo", "w");
printf2(fp, "This is a test.\n");
这种方法不使用子进程或管道,如有必要,它可以推广到多个文件指针。
在程序外部,使用“tee”:
# echo foo | tee foo.txt
foo
# cat foo.txt
foo
实际上,您可以将通道 popen() 连接到写入文件的 tee,尽管这对系统来说很繁重。有这样的效果:
FILE *stream_to_write_to = popen( "tee filename.txt" );
fprintf( stream_to_write_to, "goes to filename.txt and stdout\n" );
我很想知道是否有从-C 快速执行此操作的方法,因为在某种程度上,这涉及复制数据。很容易让两个文件句柄写入同一个地方,使用 dup() 或类似的方法,但相反的更棘手。它可能涉及推送一个模块(常见的例子是“connld”到一个流上),虽然老实说我从来没有见过这个,所以我很想自己看看一个工作代码示例。
我能给出的最佳参考是 Stevens 的“UNIX 环境中的高级编程”。
更新:
说到下面 R 的评论,上面的解决方案是一个稍微重一点的版本,只是 fork/exec-ing 并将孩子的句柄重定向到其他地方。两者都可以解决问题,虽然我更喜欢上面的方法,因为它更容易清理,但老实说,这两种解决方案都相当繁重。Fork() 不是轻量级函数。如果问题的精神是在没有 fork/exec 的情况下这样做,那么我不确定,我也很想知道。如果 fork/exec 没问题,那么直接使用它或使用 popen() 将破解它。
freopen
重定向标准输出不是一个好主意。它不一定会重用相同的文件描述符编号,因此子进程可能不会继承新的标准输出(或者最终可能根本没有标准输出)。最好使用open
thendup2
或close(0)
thenopen
为 stdout 创建一个新目标。