如何在C++程序中打开进程并将结果读入ifstream?

Chr*_*ris 2 c++ fstream process ifstream c++11

我正在编写一个将在Unix环境中运行的C++ 11程序(可移植性不是问题).目前,我有一个Makefile,它调用两个进程,一个写入文件,另一个从该文件读取.

target: mkfifo myfile other_program > myfile & my_program myfile

由于各种原因,我想从my_program中调用所有这些.看起来popen很有希望,因为它调用外部进程并提供我可以阅读的文件*.但是,我已编写的现有文件处理代码使用ifstream:

std::ifstream stream1(argv[1]);

有没有一种方法可以将popenFILE*连接到ifstream?我应该用别的东西代替popen吗?

Die*_*ühl 8

您可以创建一个从a读取的流缓冲区FILE*.显然,您可能需要更改您的代码,std::istream以备您std::ifstream在其他地方使用而不是创建流但这应该是一个直接的更改.这是一个简单的演示,演示如何创建相应的流缓冲区以及如何使用它:

#include <cstdio>
#include <iostream>

struct FILEbuf
    : std::streambuf {
    FILEbuf(FILE* fp): fp_(fp) {}
    int underflow() {
        if (this->gptr() == this->egptr()) {
            int size = fread(this->buffer_, 1, int(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];
};

int main()
{
    FILEbuf      sbuf(popen("ls -l", "r"));
    std::istream in(&sbuf);
    for (std::string line; std::getline(in, line); ) {
        std::cout << line << '\n';
    }
}
Run Code Online (Sandbox Code Playgroud)

在过去,我被告知使用popen()system()因为这些调用被认为是不安全的:这两个调用都产生了一个shell,可用于劫持他们的行为.另一种方法是创建使用文件描述符和使用流缓冲器pipe(),dup()(它的兄弟姐妹或一个), ,close(),fork()execl()(或它的兄弟姐妹中的一个)直接建立在管道上.

  • @Chris:1024是内部缓冲区的大小.如果您希望获得的数据很少,可以将其缩小; 如果你期望大量的数据,你可以把它变大.不过,我想这不会产生太大的影响. (2认同)