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

How to open a process and read the results into an ifstream from within a C++ program?

本文关键字:结果 ifstream 进程 c++ 程序      更新时间:2023-10-16

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

target: mkfifo myfile other_program > myfile & my_program myfile

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

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

有一个体面的方式来连接popen的文件* ifstream?我应该用别的东西代替popen吗?

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

#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';
    }
}

在过去,我被告知使用popen()system(),因为这些调用被认为是不安全的:这两个调用都会产生一个shell,可以用来劫持它们的行为。另一种方法是使用文件描述符创建流缓冲区,并使用pipe()dup()(或其兄弟之一)、close()fork()execl()(或其兄弟之一)直接构建管道。