سؤال

لنفترض أنني "بوبين" قابل للتنفيذ، أحصل على FILE* فى المقابل. علاوة على ذلك، لنفترض أنني أرغب في "توصيل" هذا الملف istream كائن لمعالجة أسهل، هل هناك طريقة للقيام بذلك؟

هل كانت مفيدة؟

المحلول

لا توجد طريقة قياسية ولكن إذا كنت ترغب في حل سريع، يمكنك الحصول على واصف الملف مع Fileno () ثم استخدم Josuttis " fdstream. وبعد قد تكون هناك جهود مماثلة حولها، لكنني استخدمت هذا في الماضي البعيد وعملت بشكل جيد. إذا لم يكن هناك شيء آخر يجب أن تكون خريطة جيدة جدا لتنفيذ بنفسك.

نصائح أخرى

يمكنك الابتعاد عن طريق اشتقاق STD :: Basic_Streambuf أو STD :: Streambuf الفئات.
شيء على طول هذه الخطوط:

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

بالتأكيد هناك طريقة، تنفيذ الخاصة بك istream التي يمكن بناء من FILE*.

إذا كنت تسأل عما إذا كانت هناك طريقة قياسية للقيام بذلك، فلن لا.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top