我正在使用 NDK C++ 组件编写一个 Android 项目,并且有一个需要大量解析的文件。NDK 只允许我获得一个指向我正在处理的文件的 FILE* 指针,而不是一个 ifstream ,它有一些与之相关的更多便利功能。无论如何将 FILE* (cstdio) 转换为 ifstream (iostream)?
2 回答
通常,您不能将 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);
我刚刚输入了上面的代码,目前我无法尝试。然而,基本应该是正确的,尽管可能有类型,甚至可能有一点缺陷。
请注意,没有办法检索,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
实现所需的工作之外,您无能为力。