1

我需要从我的程序中读取另一个程序的输出。为此,我可以使用 popen()。这样,我得到一个 FILE* 到可以在我的程序中解析的程序输出。如何从我的程序中读取和解析 popen() 返回值的内容?或者,在某处是否有更像 C++ 的 popen 版本?

4

2 回答 2

3

您可以创建一个流缓冲区做道德等价,popen()也可以创建一个流缓冲区包装FILE*。一旦你得到一个流缓冲区,你就可以使用它,std::istream这似乎是你打算做的。从 a 读取的简单(未经测试的)流缓冲区FILE*如下所示:

struct FILEbuf
    : std::streambuf {
    FILEbuf(FILE* fp): fp_(fp) {}
    int underflow() {
        if (this->gptr() == this->egptr()) {
            int size = fread(this->buffer_, 1, s_size, this->fp_);
            if (0 < size) {
                this->setg(this->buffer_, this->buffer_, this->buffer_ + size);
            }
        }
        return this->gptr() == this->egptr()
            ? traits_type::eof()
            : traits_type::to_int_type(*gptr());
     }
     FILE* fp_;
     enum { s_size = 1024 };
     char  buffer_[s_size];
};

我认为我打错了一些东西,但大致上这个想法确实有效:只需从FILE*流缓冲区中读取。或者,创建从衍生进程读取的流。这需要几个特定于平台的调用fork(), exec..(), pipe(), close(), dup2()(可能在这里也忘记了一些东西),但也可以完成。

可以使用像上面这样的流缓冲区,例如,像这样:

int main()
{
    FILEbuf      sbuf(fopen("pstream.cpp", "r"));
    std::istream in(&sbuf);
    for (std::string line; std::getline(in, line); ) {
        std::cout << line << '\n';
    }
}
于 2012-12-03T13:55:33.713 回答
1

FILE*调用stdio_filebuf(GNU 实现)或stdiobuf. 我认为这不是一个标准化的东西,但如果你用谷歌搜索stdiobuf你会发现它在许多平台上都可用。这是一个工作示例,说明如何将它与FILE*从 返回的指针一起使用popen,使用 gcc 4.5.0 编译并在 Linux 机器上进行测试:

#include <ext/stdio_filebuf.h>
#include <stdio.h>
#include <fstream>
#include <string>
#include <iostream>

using namespace std;

int main() {
    FILE* f = popen("ls", "r");
    __gnu_cxx::stdio_filebuf<char> fdbuf(f, std::ios::in);

    std::ifstream in;
    in.std::ios::rdbuf(&fdbuf);

    string s;
    in >> s;
    cout << s;

    pclose(f);
    return 0;
}
于 2012-12-03T14:15:36.677 回答