繁体   English   中英

如何从 C 运行外部程序并解析其输出?

[英]How can I run an external program from C and parse its output?

我有一个实用程序可以输出游戏所需的文件列表。 如何在 C 程序中运行该实用程序并获取其输出,以便我可以在同一程序中对其进行操作?

更新:关于缺乏信息的良好呼吁。 该实用程序会输出一系列字符串,这应该可以跨 Mac/Windows/Linux 移植。 请注意,我正在寻找一种编程方式来执行该实用程序并保留其输出(进入标准输出)。

正如其他人指出的那样, popen()是最标准的方式。 由于没有答案提供使用此方法的示例,因此它是:

#include <stdio.h>

#define BUFSIZE 128

int parse_output(void) {
    char *cmd = "ls -l";    

    char buf[BUFSIZE];
    FILE *fp;

    if ((fp = popen(cmd, "r")) == NULL) {
        printf("Error opening pipe!\n");
        return -1;
    }

    while (fgets(buf, BUFSIZE, fp) != NULL) {
        // Do whatever you want here...
        printf("OUTPUT: %s", buf);
    }

    if(pclose(fp))  {
        printf("Command not found or exited with error status\n");
        return -1;
    }

    return 0;
}

示例输出:

OUTPUT: total 16
OUTPUT: -rwxr-xr-x 1 14077 14077 8832 Oct 19 04:32 a.out
OUTPUT: -rw-r--r-- 1 14077 14077 1549 Oct 19 04:32 main.c

对于 Unix-ish 环境中的简单问题,请尝试popen()

从手册页:

popen() 函数通过创建管道、分叉和​​调用外壳来打开一个进程。

如果您使用阅读模式,这正是您所要求的。 我不知道它是否在Windows中实现。

对于更复杂的问题,您需要查找进程间通信。

Windows 支持 popen,请参见此处:

http://msdn.microsoft.com/en-us/library/96ayss4b.aspx

如果您希望它是跨平台的,那么 popen 是您要走的路。

好吧,假设您在 Windows 环境中使用命令行,您可以使用管道或命令行重定向。 例如,

commandThatOutputs.exe > someFileToStoreResults.txt

或者

commandThatOutputs.exe | yourProgramToProcessInput.exe

在您的程序中,您可以使用 C 标准输入函数来读取其他程序的输出(scanf 等): http : //irc.essex.ac.uk/www.iota-six.co.uk/c/c1_standard_input_and_output .asp 您还可以使用文件示例并使用 fscanf。 这也应该适用于 Unix/Linux。

这是一个非常笼统的问题,您可能希望包含更多详细信息,例如它是什么类型的输出(只是文本还是二进制文件?)以及您希望如何处理它。

编辑:万岁澄清!

重定向 STDOUT 看起来很麻烦,我不得不在 .NET 中这样做,这让我很头疼。 看起来正确的 C 方法是生成一个子进程,获取一个文件指针,突然间我的头疼了。

所以这里有一个使用临时文件的黑客。 这很简单,但它应该有效。 如果速度不是问题(击中磁盘很慢),或者如果它被扔掉,这将工作得很好。 如果您正在构建企业程序,最好使用其他人推荐的方法查看 STDOUT 重定向。

#include <stdlib.h>
#include <stdio.h>

int main(int argc, char* argv[])
{
    FILE * fptr;                    // file holder
    char c;                         // char buffer


    system("dir >> temp.txt");      // call dir and put it's contents in a temp using redirects.
    fptr = fopen("temp.txt", "r");  // open said file for reading.
                                    // oh, and check for fptr being NULL.
    while(1){
        c = fgetc(fptr);
        if(c!= EOF)
            printf("%c", c);        // do what you need to.
        else
            break;                  // exit when you hit the end of the file.
    }
    fclose(fptr);                   // don't call this is fptr is NULL.  
    remove("temp.txt");             // clean up

    getchar();                      // stop so I can see if it worked.
}

确保检查您的文件权限:现在这只会将文件放入与 exe 相同的目录中。 您可能想考虑在 nix 中使用/tmp ,或在 Vista 中使用C:\\Users\\username\\Local Settings\\Temp ,或C:\\Documents and Settings\\username\\Local Settings\\Temp in 2K/XP 我认为/tmp将在 OSX 中工作,但我从未使用过。

在 Linux 和 OS X 中, popen()确实是您最好的选择,正如 dmckee 指出的那样,因为两个操作系统都支持该调用。 在 Windows 中,这应该会有所帮助: http : //msdn.microsoft.com/en-us/library/ms682499.aspx

MSDN 文档说如果在 Windows 程序中使用,_popen 函数会返回一个无效的文件指针,导致程序无限期地停止响应。 _popen 在控制台应用程序中正常工作。 要创建重定向输入和输出的 Windows 应用程序,请参阅在 Windows SDK 中创建具有重定向输入和输出的子进程。

您可以使用system()如下所示:

system("ls song > song.txt");

其中ls是用于列出文件夹 song 内容的命令名称,而song是当前目录中的一个文件夹。 生成的文件song.txt将在当前目录中创建。

//execute external process and read exactly binary or text output
//can read image from Zip file for example
string run(const char* cmd){
    FILE* pipe = popen(cmd, "r");
    if (!pipe) return "ERROR";
    char buffer[262144];
    string data;
    string result;
    int dist=0;
    int size;
    //TIME_START
    while(!feof(pipe)) {
        size=(int)fread(buffer,1,262144, pipe); //cout<<buffer<<" size="<<size<<endl;
        data.resize(data.size()+size);
        memcpy(&data[dist],buffer,size);
        dist+=size;
    }
    //TIME_PRINT_
    pclose(pipe);
    return data;
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM