将 FILE* 转换为 ifstream C++, Android NDK

Convert FILE* to ifstream C++, Android NDK

本文关键字:C++ Android NDK ifstream FILE 转换      更新时间:2023-10-16

我正在使用 NDK C++ 组件编写一个 Android 项目,并且有一个需要大量解析的文件。NDK 只允许我获取指向我正在处理的文件的 FILE* 指针,而不是具有更多便利函数的 ifstream。有没有办法将文件*(cstdio(转换为ifstream(iostream(?

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

class stdiobuf : public std::streambuf {
private:
  FILE *d_file;
  char d_buffer[8 * 1024];
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_buffer, 8 * 1024, 1, this->d_file);
      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());
  }
};

剩下的就是初始化一个std::istream以使用stdiobuf

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

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

请注意,

没有办法检索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来实现所需工作之外,您无能为力。