将标准输出重定向到控制台并打开文件

11

给定以下函数:

freopen("file.txt","w",stdout);

将 stdout 重定向到文件,如何使 stdout 重新定向回控制台?

我要说明的是,是的,有其他类似的问题,但它们都是关于 Linux/POSIX 的。我正在使用 Windows。

你不能直接赋值给 stdout,这使得一些依赖于它的解决方案失效了。 dup 和 dup2() 不是 Windows 原生的函数,也使另一组解决方案失效。正如所说, POSIX 函数不适用于 Windows(除非你计算 fdopen() )。


1
你尝试过这里发布的一些方法吗?它们失败了吗?(顺便说一句,freopen是POSIX标准并且在Windows上可用。Windows有一些POSIX支持。) - Mat
1
@Mat:那些是针对posix系统的,根据问题描述,这里正在使用Windows。如果它有posix支持,您需要澄清它支持哪些(函数)。 - SE Does Not Like Dissent
freopen - 看看左边的链接。我不需要澄清任何事情。您发布一个在Windows上有效的函数调用问题,还有类似的问题也使用Windows可用的API。 (需要进行研究的人是您自己-您是遇到问题的人。) - Mat
2
你必须要做的事情,不是真的@ Mat,或者任何其他人都不需要这样做,没有人在这里得到支付来帮助。 至少向那些帮助你的人表达一点感激之情,而不是对他们提出要求 - Alok Save
2
@Als:我不熟悉这个系统。如果我知道什么有效,什么无效,我就不会问问题了。他得向我展示,因为我自己不知道。 - SE Does Not Like Dissent
5个回答

18

您可以使用_dup来实现此功能。

以下类似的代码应该可以工作(或者您可能更喜欢在_dup文档中列出的示例):

#include <io.h>
#include <stdio.h>

...
{
    int stdout_dupfd;
    FILE *temp_out;

    /* duplicate stdout */
    stdout_dupfd = _dup(1);

    temp_out = fopen("file.txt", "w");

    /* replace stdout with our output fd */
    _dup2(_fileno(temp_out), 1);
    /* output something... */
    printf("Woot!\n");
    /* flush output so it goes to our file */
    fflush(stdout);
    fclose(temp_out);
    /* Now restore stdout */
    _dup2(stdout_dupfd, 1);
    _close(stdout_dupfd);
}

有没有可能直接写出 stdout 而不是所有这些东西? - Sandburg
@Sandburg:如果这不是特定于Windows的,你可以包含 unistd.h 并写入 STDOUT_FILENO(或自己定义 STDOUT_FILENO 为1)。在此之前,您还可以使用 _fileno 来获取 stdout 文件描述符。 - Hasturkun

17

另一种解决方案是:

freopen("CON","w",stdout);

根据维基百科的说法,"CON"是一个特殊的关键字,指的是控制台。


1
我尝试了这个 - Win7,VS2017 - 不幸的是它没有工作。 - Thomas Schmid
2
我测试了一下,是的,它可以工作。这就是我一直在寻找的解决方案。非常感谢您的帮助@dtyler。 - gyurix
1
在哪个环境下?对我而言,只有使用 _dup2() 函数才有效。 - Thomas Schmid
实际上,CON:、AUX:等与COM1:、A:或C:是完全相同的...换句话说,它们都是设备。只不过Unix将它们仅放在/dev/中作为物理“文件”,而在DOS中它们则是虚拟存在于“每个目录”中(大多数版本实际上有一个错误,如果你特别输入这些名称,dir命令会显示它们),并不是一个“特殊关键字”。只是一个指向设备的文件名,就像任何其他字符或块设备一样。 - HRH Sven Olaf of CyberBunker

4

在回答后,我注意到这是一个特定于Windows的问题。以下内容可能对其他人的问题有用。Windows也提供了_fdopen,因此将0更改为正确的HANDLE可能会将Linux解决方案修改为Windows。

stdout = fdopen(0, "w")

#include <stdio.h>
#include <stdlib.h>
int main()
{
    freopen("file.txt","w",stdout);
    printf("dupa1");
    fclose(stdout);
    stdout = fdopen(0, "w");
    printf("dupa2");
    return 0;
}

fdopen是有效的。而dup和dup2不是,根据hasturkun所说,在Windows中它们被称为_dup和_dup2。为你的努力点赞。(忽略我关于编译器错误的说法...那是我的错)。 - SE Does Not Like Dissent
1
我会在那里加上 stdout = fdopen(0, "w");,结果出现以下错误:需要左值作为赋值运算符的左操作数。 - SE Does Not Like Dissent

0

这对我有效

#include <stdio.h>
int main()
{

    FILE* original_stdout = stdout;
    stdout = fopen("new_stdout.txt", "w");
    printf("ciao\n");
    fclose(stdout);
    stdout = original_stdout;
    printf("a tutti\n");
    return 0;
}

0

请注意,stdin、stdout和stderr(0、1、2)的文件描述符不一定与printf()等使用的“特殊变量”相同。虽然在大多数情况下,它们在程序启动时输出到相同的设备上(如果您在程序运行期间更改了某些内容或tty重定向已应用,则除外)。stdin、stdout和stderr是FILE*指针。两个概念需要单独“重定向”,各自使用自己的方法…'dup2'用于复制文件描述符,而不是FILE *指针。对于类似stdin、stdout和stderr这样的FILE *指针...'freopen()'..但这实际上只会影响printf和其派生函数。


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