- 此问题在此处已有答案**:
C++: Redirecting STDOUT(7个答案)
6个月前关闭。
这篇文章是昨天编辑并提交审查的。
"我想做的事"
从c++内部将stdout和stderr重定向到一个或多个文件
"为什么我需要它"
我正在使用一个外部的、预编译的第三方库,它产生了大量的输出,我希望将其重定向到一个日志文件以保持控制台干净。
- 条件**
兼容性不是问题,代码只能在Unix系统上运行。重定向不仅会影响c++风格的打印(std::cout << "hello world" << std::endl
),还会影响c风格的打印(printf("hello world\n")
)。
"我所尝试的"
我在stackoverflow上浏览了半天,读到了很多有类似问题的人的回答,在这些回答的帮助下,我已经能够整理出下面的代码:
#include <stdio.h>
#include <iostream>
#include <fcntl.h>
#include "unistd.h"
const int stdoutfd(dup(fileno(stdout)));
int redirect_stdout(const char* fname){
fflush(stdout);
int newstdout = open(fname, O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
dup2(newstdout, fileno(stdout));
close(newstdout);
}
int restore_stdout(){
fflush(stdout);
dup2(stdoutfd, fileno(stdout));
close(stdoutfd);
return stdoutfd;
}
int main(){
redirect_stdout("/dev/null");
std::cout << "invisible 1" << std::endl;
restore_stdout();
std::cout << "visible 1" << std::endl;
redirect_stdout("/dev/null");
std::cout << "invisible 2" << std::endl;
restore_stdout();
std::cout << "visible 2" << std::endl;
return 0;
}
我希望看到的是:
visible 1
visible 2
我真正看到的
visible 1
也就是说,当第一次使用这个机制时,它是有效的--但如果再次使用,恢复输出将不起作用。有人能告诉我,为了让这个机制无限频繁地工作,我需要做什么改变吗?
- 编辑:为什么它与其他人正在做的事情不同?**
许多人都有类似的问题(因此有了"再次",例如here)。然而,在这里,我特别针对一个适用于C
风格和C++
风格打印的解决方案,并特别关注函数的可重用性-这在其他问题和答案中通常没有解决。
6条答案
按热度按时间kyvafyod1#
除了freopen()的afr0ck答案之外,我想说的是,当使用
freopen()
时,我们应该小心。一旦像stdout
或stdin
这样的流被重新打开并分配了新的目标(这里是**'output.txt'**文件),它总是为程序保留,除非它被显式地更改。这里标准输出流
stdout
被重新打开并被分配了**'output.txt'文件。此后,每当我们使用printf()
或任何其他stdout
流(如-putchar()
)时,每个输出都将转到'output.txt'**。(即在控制台/终端中打印输出),我们可以使用以下代码行-freopen("/dev/tty", "w", stdout);
freopen("CON", "w", stdout);
请参见下面的代码示例-
此代码在当前目录中生成一个**“output.txt”文件,并且No#2和No#3将在“output.txt”**文件中打印。
谢谢
z8dt9xmd2#
如果您希望能够重用它,请不要关闭
restore_stdout
中的stdoutfd
。e4yzc0pl3#
你在找这样的东西吗
根据我之前的回答
klh5stk14#
那么我最好使用freopen()
用法语法:
“stderr”也是如此
dz6r00yl5#
对于C++ iostreams,您可以使用
rdbuf
的非常数重载将std::cout
设置为std::filebuf
。(最好通过RAII类来完成,因为您必须在离开main之前恢复它。)对于CFILE*
,您可以使用freopen
,但我不认为您能够恢复它。FWIW:这两种解决方案都只使用标准的C++或C,所以应该是可移植的。
xghobddn6#
@POW和@JamesKanze的回答启发了我,我编写了一个RAII类,用于将
std::cout
重定向到一个文件,目的是演示这个原理。代码:
输出:
此消息将打印到屏幕上
再次打印到屏幕
文件
"output.txt"
的内容:此消息转到文件