简体   繁体   English

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

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

I am writing a C++11 program that will run in a Unix environment (portability isn't a concern). 我正在编写一个将在Unix环境中运行的C ++ 11程序(可移植性不是问题)。 Currently, I have a Makefile that invokes two processes, one which writes to a file and the second which reads from that file. 目前,我有一个Makefile,它调用两个进程,一个写入文件,另一个从该文件读取。

target: mkfifo myfile other_program > myfile & my_program myfile

For various reasons, I want invoke all of this from within my_program. 由于各种原因,我想从my_program中调用所有这些。 It looks like popen is promising, as it invokes an external process and provides a FILE* I can read. 它看起来像popen是有前途的,因为它调用外部进程并提供我可以阅读的文件*。 However, the existing file processing code I've already written uses ifstream: 但是,我已编写的现有文件处理代码使用ifstream:

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

Is there a decent way to connect popen 's FILE* to an ifstream? 有没有一种方法可以将popen的FILE *连接到ifstream? Is there something else I should use instead of popen ? 还有什么我应该用而不是popen吗?

You can create a stream buffer which reads from a FILE* . 您可以创建一个从FILE*读取的流缓冲区。 Clearly, you may need to change your code to use std::istream in case you use std::ifstream in other places than creating the stream but this should be a straight forward change. 显然,您可能需要更改代码以使用std::istream ,以防您在其他地方使用std::ifstream而不是创建流,但这应该是一个直接的更改。 Here is a simple demo showing how to create a corresponding stream buffer and how to use it: 这是一个简单的演示,演示如何创建相应的流缓冲区以及如何使用它:

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

In the past I have been told off for using popen() or system() because these calls are considered to be unsafe: both of these calls spawn a shell which can be used to hijack their behavior. 在过去,我被告知使用popen()system()因为这些调用被认为是不安全的:这两个调用都会产生一个shell,可以用来劫持他们的行为。 The alternative is to create a stream buffer using file descriptors and using pipe() , dup() (or one of its siblings), close() , fork() , and execl() (or one of its siblings) to build the pipe directly. 另一种方法是使用文件描述符创建一个流缓冲区,并使用pipe()dup() (或其中一个兄弟), close()fork()execl() (或其中一个兄弟)来构建直接管道。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM