我想重新打开stdin
和stdout
(可能是stderr
,而我正在使用它)文件句柄,以便将来调用printf()
或{{1或putchar()
将转到某个文件,以后对puts()
的调用将来自文件。
1)我不想永久丢失标准输入/输出/错误。我可能希望稍后在程序中重用它们。
2)我不想打开新的文件句柄,因为这些文件句柄必须要经过大量传递或全局传递(不寒而栗)。
3)如果我无法帮助,我不想使用任何getc()
或open()
或其他与系统相关的功能。
基本上,这样做是否有效:
fork()
而且,如果确实如此,我怎样才能获得stdin = fopen("newin", "r");
的原始值?我是否必须将其存储在stdin
中并稍后再取回?
答案 0 :(得分:78)
为什么要使用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);
答案 1 :(得分:15)
我认为你正在寻找像freopen()
答案 2 :(得分:10)
这是Tim Post方法的修改版本;我使用/ dev / tty而不是/ dev / stdout。我不知道为什么它不适用于stdout (这是/ proc / self / fd / 1的链接):
freopen("log.txt","w",stdout);
...
...
freopen("/dev/tty","w",stdout);
通过使用/ dev / tty,输出被重定向到启动应用程序的终端。
希望此信息有用。
答案 3 :(得分:9)
os函数dup2()应该提供你需要的东西(如果没有提到你需要的东西)。
更具体地说,您可以将stdin文件描述符dup2()转换为另一个文件描述符,使用stdin执行其他操作,然后在需要时将其复制回来。
dup()函数复制打开的文件描述符。具体来说,它使用F_DUPFD常量命令值为fcntl()函数提供服务的备用接口,第三个参数为0。重复的文件描述符与原始文件描述符共享任何锁定。
成功时,dup()返回一个新的文件描述符,该描述符与原始文件具有以下共同点:
- 相同的打开文件(或管道)
- 相同的文件指针(两个文件描述符共享一个文件指针)
- 相同的访问模式(读,写或读/写)
答案 4 :(得分:9)
freopen("/my/newstdin", "r", stdin);
freopen("/my/newstdout", "w", stdout);
freopen("/my/newstderr", "w", stderr);
... do your stuff
freopen("/dev/stdin", "r", stdin);
...
...
这针在我的圆钉方孔o表上,你想要完成什么?
修改强>
请记住,对于每个新创建的进程,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()的预期行为,正如您所看到的,您仍然只使用三个文件描述符(和相关的流)。
这将覆盖任何shell重定向,因为shell没有任何重定向。然而,它可能会打破管道。您可能希望确保为SIGPIPE设置处理程序,以防程序发现自己位于管道的阻塞端(而不是FIFO,管道)。
因此,./your_program --stdout /tmp/stdout.txt --stderr /tmp/stderr.txt应该可以使用freopen()轻松完成,并保持相同的实际文件描述符。我不明白为什么你一旦改变它们就需要把它们放回去?当然,如果有人通过了任何一个选项,他们会希望它一直持续到程序终止?
答案 5 :(得分:3)
freopen
解决了简单的问题。如果您没有阅读任何内容,并且您愿意使用POSIX系统调用dup
或dup2
,那么保持旧的stdin并不难。如果你开始阅读它,所有的赌注都会被取消。
也许您可以告诉我们出现此问题的背景?
我建议您坚持放弃旧stdin
和stdout
的情况,因此可以使用freopen
。
答案 6 :(得分:3)
与此同时,有一个C源代码库可以为您完成所有这些,重定向stdout或stderr。但很酷的部分是,它允许您根据需要为截获的流分配尽可能多的回调函数,这样您就可以非常轻松地将单个消息发送到多个目标,数据库,文本文件等。
最重要的是,创建看起来和行为与stdout和stderr相同的新流变得微不足道,您可以将这些新流重定向到多个位置。
在* oogle上查找U-Streams C库。
答案 7 :(得分:0)
这是最方便实用的方式
freopen("dir","r",stdin);