C++:将子进程输出发送到标准输入

11
假设我想从程序中调用子进程,并希望将该子进程的输出读取到我的程序中。下面是一种简单的方法:
//somefile.cpp
system("sub_process arg1 arg2 -o file.out");
           //call the subprocess and have it write to file
FILE *f = std::fopen("file.out", "r");
//.... and so on
我们都知道I/O操作在计算机中是比较慢的。为了加速这个过程,我希望能够跳过写入文件再从文件读取的步骤,而是直接将子进程的输出直接重定向到stdin(或其他流)。
如何做到这一点?如何跳过I/O操作?
注意:许多程序在运行时会向stdout输出一些诊断信息,并将输出的干净版本写入stdout(例如:stdout:"step1...done, step2...done, step3..done" -o file-out:"The magic number is: 47.28"),因此忽略“-o”参数并相信输出将自动重新定向到stdout并不一定有用...
提前感谢大家的帮助。

关于您对 -o 的评论以及其所产生的影响,大多数程序都会有严格的输出定义,而您的程序可以进行过滤。 - Dan
1
+CycoMatto,你是不是想说“在运行时将一些诊断信息输出到stderr,并将输出的干净版本写入stdout。”考虑一个程序,它将一些输出输出到“-o文件”,一些输出输出到stdout,还有一些输出输出到stderr。你希望访问这三个中的哪一个? - Aaron McDaid
@AaronMcDaid 是的,这是我关键的误解。谢谢你的澄清!请看下面我对dasblinkenlight的回应。 - cmo
2个回答

8
使用popen跳过文件,通过内存缓冲区获取命令的输出。
#include <iomanip>
#include <iostream>
using namespace std;
const int MAX_BUFFER = 255;
int main() {
    string stdout;
    char buffer[MAX_BUFFER];
    FILE *stream = popen("command", "r");
    while ( fgets(buffer, MAX_BUFFER, stream) != NULL )
        stdout.append(buffer);
    pclose(stream);
    cout << endl << "output: " << endl << stdout << endl;
}

我猜输出内容相当大,将占用远超过255字节的空间。+CycoMatto,你能澄清一下你期望的输出大小吗? - Aaron McDaid
@AaronMcDaid 没关系 - 程序将以每256字节为一组读取输出。如果这被证明是性能问题,可以随时更改缓冲区的大小。我喜欢从小处开始,等到分析工具指出它成为瓶颈时再采取行动。 - Sergey Kalinichenko
1
@CycoMatto,你只能获得stdout的输出内容,而不是通常发送到stderr的“调试垃圾”。你看到这两个混在一起,因为它们都送到同一个控制台,但内部它们是分开的流。如果你计划运行的进程向stdout发送“偏离的输出”,那么你将不得不自行过滤它。但大多数UNIX程序在这方面都表现良好,所以我认为你应该尝试一下。 - Sergey Kalinichenko
1
我经常想,shell/终端/任何东西都应该找到一种方法来着色stderr,以便不会发生这种混淆。 - Aaron McDaid
2
@CycoMatto popen 是 UNIX 的系统调用,而不是 C/C++ 库函数。这就是为什么它不是命名空间的一部分。 - Sergey Kalinichenko
显示剩余4条评论

3

如果你使用的是Windows操作系统:

请按照以下步骤进行:http://support.microsoft.com/kb/190351

这篇文章详细地介绍了如何进行重定向,让你可以在任何地方都能实现它。


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