Frage

Angenommen, ich „popen“ eine ausführbare Datei, habe ich eine FILE* im Gegenzug zu bekommen. Außerdem nehme ich würde diese Datei zu einem istream Objekt für eine leichtere Verarbeitung zu „verbinden“ mögen, ist es eine Möglichkeit, dies zu tun?

War es hilfreich?

Lösung

Es gibt keinen Standard-Weg, aber wenn Sie eine schnelle Lösung wollen, können Sie den Dateideskriptor mit fileno () und dann Josuttis verwenden fdstream . Es können ähnliche Bemühungen um, aber ich verwendet, um dieses in der fernen Vergangenheit und es funktionierte gut. Wenn nichts anderes sollte es eine sehr gute Karte sein, Ihre eigenen zu implementieren.

Andere Tipps

Sie können wegkommen std :: basic_streambuf oder std :: streambuf Klassen durch Ableiten.
Etwas in diese Richtung:

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

Sicher gibt es eine Möglichkeit, Ihre eigenen istream implementieren, die von einem FILE* aufgebaut werden kann.

Wenn Sie sich fragen, ob es eine standardisierte Möglichkeit, dies zu tun, dann nicht.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top