在C++中读取popen结果

12

我正在编写一个C++应用程序,需要读取系统命令的结果。

我正在使用popen(),基本上像这样:

    const int MAX_BUFFER = 2048;
    string cmd="ls -l";
    char buffer[MAX_BUFFER];
    FILE *stream = popen(cmd.c_str(), "r");
    if (stream){
       while (!feof(stream))
       {
            if (fgets(buffer, MAX_BUFFER, stream) != NULL)
            {
               //here is all my code
            }
       }
       pclose(stream);
    }

我一直试图以不同的方式重写这个。我看到了一些非标准的解决方案,比如:

FILE *myfile;
std::fstream fileStream(myfile);
std::string mystring;
while(std::getline(myfile,mystring))
{
    // .... Here I do what I need
}

然而,我的编译器不接受这个。

我该如何在C++中使用popen读取数据?


“here all my code” 是什么意思?如果是 data.append(buffer);,你的第一个解决方案完美地运作了。 - Beta
1
你能发布一下崩溃时的调用栈吗? - user3458
请提供一个最小化的、完整的程序,以演示您的错误。从您的实际程序开始,删除所有正常工作的行,只显示剩下的内容。这里是您第一段代码片段的工作实现示例。有关使用此技术的更多信息,请参见http://sscce.org。 - Robᵩ
尝试过了,但还是崩溃了。 如果结果为空,我就不明白读取的是什么了... - Stefano
1
伙计们...我非常非常抱歉...但你们是对的...错误在其他地方...我一直处于盲目状态,确信错误就在那里,但实际上不是!...为一直坚持而感到非常抱歉。 - Stefano
显示剩余9条评论
2个回答

16
你的例子:
FILE *myfile;
std::fstream fileStream(myfile);
std::string mystring;
while(std::getline(myfile,mystring))

不能工作,因为尽管你非常接近,但标准库没有提供可以从FILE*构造的fstreamBoost iostreams提供了一个可以从文件描述符构造的iostream,你可以通过调用fileno来获取一个FILE*

例如:

typedef boost::iostreams::stream<boost::iostreams::file_descriptor_sink>
        boost_stream; 

FILE *myfile; 
// make sure to popen and it succeeds
boost_stream stream(fileno(myfile));
stream.set_auto_close(false); // https://svn.boost.org/trac/boost/ticket/3517
std::string mystring;
while(std::getline(stream,mystring))

别忘了稍后还要使用pclose

注意:更新的boost版本已经弃用了仅接受fd参数的构造函数。相反,您需要将boost::iostreams::never_close_handleboost::iostreams::close_handle作为必填的第二个参数传递给构造函数。


一些编译器为标准C++库提供非标准扩展。接受FILE*类型参数的fstream构造函数就是其中流行的一个。这也解释了为什么它在某些编译器上能够工作而在其他编译器上则不能。 - Sjoerd
@Sjoerd - 啊,是的,那样做就有意义了。我想知道为什么会这样编写。不过,在配置构建工具时,您仍然可以使用typedef在非标准扩展和boost库之间进行选择。 - Flexo
1
我尝试使用fstream的标准构造函数,但在我的情况下未被接受。我现在将尝试这种方式... - Stefano
2
编译失败了,我猜应该把sink改成source,因为这是一个只读的例子。boost::iostreams::file_descriptor_source - Terry Shi

-4

这是我很久以前写的东西,可能会对你有所帮助。它可能存在一些错误。

#include <vector>
#include <string>
#include <stdio.h>
#include <iostream>

bool my_popen (const std::string& cmd,std::vector<std::string>& out ) {
    bool            ret_boolValue = true;
    FILE*           fp;
    const int       SIZEBUF = 1234;
    char            buf [SIZEBUF];
    out = std::vector<std::string> ();
    if ((fp = popen(cmd.c_str (), "r")) == NULL) {
        return false;
    }
    std::string  cur_string = "";
    while (fgets(buf, sizeof (buf), fp)) {
        cur_string += buf;
    }
    out.push_back (cur_string.substr (0, cur_string.size () - 1));
    pclose(fp);
    return true;
}
int main ( int argc, char **argv) {
        std::vector<std::string> output;
        my_popen("ls -l > /dev/null ", output);
        for ( std::vector<std::string>::iterator itr = output.begin();
                                                 itr != output.end();
                                                 ++itr) {
                std::cout << *itr << std::endl;
        }

}

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