标准输出重定向是如何工作的?

5

以下代码将标准输出重定向到文件fname,然后再重定向回原始的标准输出。对我来说它工作得很好。但我无法理解它是如何工作的。如果有人能帮助我理解,我会非常感激。

    printf("\n This is console");
    fflush(stdout);
    fgetpos(stdout, &pos);
    fd = dup(fileno(stdout));
    freopen(fname, "a+", stdout);   

    printf("inside file op");  

    fflush(stdout);
    dup2(fd,fileno(stdout));
    close(fd);
    clearerr(stdout);
    fsetpos(stdout, &pos);
    printf("\nBack to Console");

是的,明白了。我会记住的。谢谢 :) - vindyz
2
伟大的上帝啊,为什么有人想要做那件事呢?(除了作为一种绝望的最后手段来解决一个坚持写入标准输出的无源代码库之外)。 - hmakholm left over Monica
如果有人想将不同的日志消息重定向到不同的文件以进行调试,那么这非常方便。 - vindyz
1
你应该放弃现有的日志基础设施,转而使用一些能够以更合理的方式控制目标地点的工具。 - hmakholm left over Monica
1个回答

14

我们逐行分析它。第一行将某些内容输出到stdout

printf("\n This is console");

然后它刷新 stdout ,这样缓冲区中剩余的数据就会被发送到 stdout ,并且不会与文件数据混合:

fflush(stdout);

现在我们将自己的当前位置存储在 stdout 中,因为如果 stdout 已经指向一个文件,我们可能会覆盖之前的部分。

fgetpos(stdout, &pos);

现在我们克隆当前 stdout 的文件描述符。由于我们即将更改 stdout 指向的位置,因此需要保留原始副本:

fd = dup(fileno(stdout));

现在我们已经保存了所有内容,我们可以将stdout重新打开为文件:

freopen(fname, "a+", stdout);

此时,stdout 已经被重定向到文件中了。我们现在可以将内容打印到文件中:

printf("inside file op");  

现在我们已经将内容打印到文件中了。我们需要刷新 stdout(现在是文件),以防它与正常的 stdout 数据混合:

fflush(stdout);

之后,我们将原始的stdout文件描述符克隆到当前stdout描述符上。

dup2(fd,fileno(stdout));

现在可以关闭克隆的那个了:

close(fd);

我不太确定这段代码的作用,但是它可以清除写入文件时出现的任何错误:

clearerr(stdout);

现在我们恢复stdout的位置。据我所知,只有在它最初被重定向到一个文件时才有用:

fsetpos(stdout, &pos);

现在我们回到了原始的stdout,因此我们可以再次打印:

printf("\nBack to Console");

听起来很不错...现在更清楚了。谢谢,感激不尽。 - vindyz
我认为它现在已经相当高效了。如果你想更加高效,你可能可以跳过标准C库(除了fflush,你可能想保留它),直接使用系统调用(如dupdup2close),但我认为你不会从中获得太多好处。 - icktoofay
使用freopen的方式是不安全的。相反,您应该简单地打开新文件(或fopen它然后获取其fileno),并将其dup2到文件描述符1上。 - R.. GitHub STOP HELPING ICE

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接