4

我正在使用 NDK C++ 组件编写一个 Android 项目,并且有一个需要大量解析的文件。NDK 只允许我获得一个指向我正在处理的文件的 FILE* 指针,而不是一个 ifstream ,它有一些与之相关的更多便利功能。无论如何将 FILE* (cstdio) 转换为 ifstream (iostream)?

4

2 回答 2

5

通常,您不能将 a 转换FILE*std::ifstream. 但是,无论如何这并不是必需的:创建一个可用于初始化std::istream. 使用 anstd::istream应该就足够了,因为 by 提供的额外功能std::ifstream无论如何都不能真正帮助解析。只要您不需要使用 seek,创建一个用于从 a 读取的流缓冲区FILE*就非常简单。所需要的只是覆盖该std::streambuf::underflow()函数:

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());
    }
};

剩下的就是初始化 astd::istream以使用 a stdiobuf

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

我刚刚输入了上面的代码,目前我无法尝试。然而,基本应该是正确的,尽管可能有类型,甚至可能有一点缺陷。

于 2012-09-09T20:45:51.957 回答
3

请注意,没有办法检索,std::ifstream但您可以获得std::istream.

虽然不是标准 C++ 的一部分,但有时会通过构造函数std::basic_filebuf公开扩展,该构造函数采用.std::FILE *

basic_filebuf(FILE *fp, char_type *buf = 0, 
              streamsize n = /* default size */);

构造一个类的对象basic_filebuf,用 初始化基类basic_streambuf<charT,traits>()。然后它调用open(fp, buf, n).

你应该使用它的方式如下......

FILE *pf = ...; /* e.g. fopen("/etc/passwd", "r") */
std::filebuf buf(pf);
std::istream stream(&buf);

现在,如果这个扩展不可用,那么恐怕除了尝试实现自己的std::streambuf实现所需的工作之外,您无能为力。

于 2012-09-09T20:18:29.680 回答