Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Convert FILE* to ifstream C++, Android NDK

I'm coding an Android project with an NDK C++ component and have a file that needs a lot of parsing. The NDK only allows me to get a FILE* pointer to the file that I'm dealing with, not an ifstream which has a few more convenience functions associated with it. Is there anyway to convert an FILE* (cstdio) to ifstream (iostream)?

like image 712
sparkFinder Avatar asked Feb 19 '23 05:02

sparkFinder


1 Answers

In general, you can not convert a FILE* to an std::ifstream. However, this isn't really necessary anyway: It is reasonable straight forward to create a custom stream buffer which can be used to initialize an std::istream. Using an std::istream should be sufficient because the extra functionality provided by std::ifstream doesn't really help with parsing anyway. As long as you don't need to use seeking, creating a stream buffer for reading from a FILE* is really simple. All it takes is overriding the the std::streambuf::underflow() function:

class stdiobuf
    : std::streambuf
{
private:
    FILE* d_file;
    char  d_buffer[8192];
public:
    stdiobuf(FILE* file): d_file(file) {}
    ~stdiobuf() { if (this->d_file) fclose(this->d_file); }
    int underflow() {
        if (this->gptr() == this->egptr() && this->d_file) {
            size_t size = fread(this->d_file, 8192);
            this->setg(this->d_buffer, this->d_buffer, this->d_buffer + size);
        }
        return this->gptr() == this->egptr()
            ? traits_type::eof()
            : traits_type::to_int_type(*this->gptr());
    }
};

All what remains is to initialize an std::istream to use a stdiobuf:

stdiobuf     sbuf(fopen(...));
std::istream in(&sbuf);

I just typed in the above code and currently I can't try it out. However, the basic should be correct although there may be types and possibly even a little flaw.

like image 148
Dietmar Kühl Avatar answered Feb 26 '23 19:02

Dietmar Kühl