2008-09-04 45 views
44

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

更新:良好的信息缺乏通话。该实用程序吐出一系列字符串,并且这应该是Mac/Windows/Linux中完全可移植的。请注意,我正在寻找一种编程方式来执行该实用程序并保留它的输出(转到stdout)。

+0

也看到http://stackoverflow.com/questions/125828/capturing-stdout-from-a-system-command-optimally – rogerdpack 2012-09-25 22:30:32

+0

如果你想要stderr以及你可以重定向,例如调用ls nonexistant-name 2>&1 – Vic 2013-04-10 03:11:25

+5

这不是重复的;链接的问题是** C++特定的**,而这个问题是关于** C **的。 – 2016-03-22 22:21:33

回答

45

对于Unix的十岁上下的环境中的简单问题尝试popen()

从手册页:

的POPEN()函数创建一个管道,分叉和调用外壳打开一个过程。

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

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

+20

如何正确使用`popen()`的一些例子会很好。 – 2013-07-29 19:29:49

7

好吧,假设你是在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上运行,但我从来没有使用过。

2

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

0
//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; 
} 
1

您可以使用system()为:

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

其中ls是命令名称列出文件夹的歌曲的内容和song是在当前目录中的文件夹。生成的文件song.txt将在当前目录中创建。

29

正如其他人所指出的,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; 
} 
相关问题