Pregunta

Supongamos que "popen" un ejecutable, consigo un FILE* a cambio. Además, supongo que me gustaría "conectar" este archivo a un objeto istream para un procesamiento más fácil, hay una manera de hacer esto?

¿Fue útil?

Solución

No hay manera estándar, pero si quieres una solución rápida que pueda obtener el descriptor de archivo con fileno () y luego usar Josuttis' fdstream . Es posible que haya esfuerzos similares en todo pero utilizado en el pasado distante y funcionó bien. Por lo menos debe ser un muy buen mapa para implementar su propio.

Otros consejos

Puede salirse derivando std :: basic_streambuf o std :: streambuf clases.
Algo a lo largo de estas líneas:

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

#define BUFFER_SIZE     1024

class popen_streambuf : public std::streambuf {
public:
    popen_streambuf() : fp(NULL) {
    }
    ~popen_streambuf() {
        close();
    }
    popen_streambuf *open(const char *command, const char *mode) {
        fp = popen(command, mode);
        if (fp == NULL)
            return NULL;
        buffer = new char_type[BUFFER_SIZE];
        // It's good to check because exceptions can be disabled
        if (buffer == NULL) {
            close();
            return NULL;
        }
        setg(buffer, buffer, buffer);
        return this;
    }
    void close() {
        if (fp != NULL) {
            pclose(fp);
            fp = NULL;
        }
    }
    std::streamsize xsgetn(char_type *ptr, std::streamsize n) {
        std::streamsize got = showmanyc();
        if (n <= got) {
            memcpy(ptr, gptr(), n * sizeof(char_type));
            gbump(n);
            return n;
        }
        memcpy(ptr, gptr(), got * sizeof(char_type));
        gbump(got);

        if (traits_type::eof() == underflow()) {
            return got;
        }
        return (got + xsgetn(ptr + got, n - got));
    }
    int_type underflow() {
        if (gptr() == 0) {
            return traits_type::eof();
        }
        if (gptr() < egptr()) {
            return traits_type::to_int_type(*gptr());
        }
        size_t len = fread(eback(), sizeof(char_type), BUFFER_SIZE, fp);
        setg(eback(), eback(), eback() + (sizeof(char_type) * len));
        if (0 == len) {
            return traits_type::eof();
        }
        return traits_type::to_int_type(*gptr());
    }
    std::streamsize showmanyc() {
        if (gptr() == 0) {
           return 0;
        }
        if (gptr() < egptr()) {
            return egptr() - gptr();
        }
        return 0; 
    }
private:
    FILE *fp;
    char_type *buffer;
};

int main(int argc, char *argv)
{
    char c;
    popen_streambuf sb;
    std::istream is(&sb);

    if (NULL == sb.open("ls -la", "r")) {
        return 1;
    }

    while (is.read(&c, 1)) {
        std::cout << c;
    }

    return 0;
}

Por supuesto que hay una manera, poner en práctica su propia istream que puede ser construido a partir de una FILE*.

Si estás preguntando si hay una manera estándar de hacer esto, entonces no.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top