gpt4 book ai didi

c++ - 如何读取尚未刷新的进程输出?

转载 作者:IT老高 更新时间:2023-10-28 23:14:01 24 4
gpt4 key购买 nike

考虑把这个小程序编译成application.exe

#include <stdio.h>

int main()
{
char str[100];
printf ("Hello, please type something\n");
scanf("%[^\n]s", &str);
printf("you typed: %s\n", str);
return 0;
}

现在我使用这段代码来启动 application.exe 并获取它的输出。

#include <stdio.h>
#include <iostream>
#include <stdexcept>

int main()
{
char buffer[128];
FILE* pipe = popen("application.exe", "r");
while (!feof(pipe)) {
if (fgets(buffer, 128, pipe) != NULL)
printf(buffer);
}
pclose(pipe);
return 0;
}

我的问题是在我输入之前没有输出。然后获取两条输出线。我可以通过在第一个 printf 语句之后添加这一行来解决这个问题。

fflush(stdout);

然后在我按预期输入之前获取第一行。

但是我如何才能获取我无法修改的应用程序的输出,并且不使用 fflush() 在“实时”(意味着在它们退出之前)? .而windows cmd是怎么做到的呢?

最佳答案

C 程序中自动打开的流的缓冲会随着所连接设备的类型而变化,这一事实让您感到困扰。

这有点奇怪——让 *nixes 很好玩的一件事(这反射(reflect)在 C 标准库中)是进程不太关心他们从哪里获取数据以及从哪里写入数据.您只需在闲暇时进行管道和重定向,它通常是即插即用的,而且速度非常快。

此规则打破的一个明显地方是交互;你举了一个很好的例子。如果程序的输出是 block 缓冲的,您可能在累积 4k 数据之前看不到它,或者进程退出。

程序可以通过 isatty() 检测它是否写入终端(也可能通过其他方式)。终端在概念上包括用户,建议交互式节目。打开 stdin 和 stdout 的库代码检查并将它们的缓冲策略更改为行缓冲:当遇到换行符时,将刷新流。这对于交互式、面向行的应用程序来说是完美的。 (对于行编辑来说,它并不完美,因为 bash 会完全禁用缓冲。)

open group man page for stdin在缓冲方面相当模糊,以便为实现提供足够的余地以提高效率,但它确实说:

the standard input and standard output streams are fully buffered if and only if the stream can be determined not to refer to an interactive device.

这就是您的程序所发生的情况:标准库看到它正在“非交互式”运行(写入管道),尝试变得聪明高效并打开 block 缓冲。写入换行符不再刷新输出。通常这是一件好事:想象一下写入二进制数据,平均每 256 个字节写入磁盘!太可怕了。

值得注意的是,在您和磁盘之间可能存在整个级联的缓冲区;在 C 标准库之后是操作系统的缓冲区,然后是磁盘。

现在你的问题是:用于存储要写入的字符的标准库缓冲区位于程序的内存空间中。尽管看起来,数据还没有离开你的程序,因此其他程序不能(官方)访问。我觉得你运气不好。您并不孤单:大多数交互式控制台程序在尝试通过管道操作时都会表现不佳。

关于c++ - 如何读取尚未刷新的进程输出?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39389017/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com