我正在编写一个带有NDK C ++组件的Android项目,并且有一个需要大量解析的文件。 NDK只允许我获取一个指向我正在处理的文件的FILE *指针,而不是一个ifstream,它有一些与之相关的便利功能。无论如何将FILE *(cstdio)转换为ifstream(iostream)?
答案 0 :(得分:5)
通常,您可以不将FILE*
转换为std::ifstream
。但是,这无论如何都不是必需的:创建一个可用于初始化std::istream
的自定义流缓冲区是合理的。使用std::istream
应该足够了,因为std::ifstream
提供的额外功能无论如何都不能真正帮助解析。只要您不需要使用搜索,创建用于从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());
}
};
剩下的就是初始化std::istream
以使用stdiobuf
:
stdiobuf sbuf(fopen(...));
std::istream in(&sbuf);
我刚输入上面的代码,目前我无法尝试。然而,基本应该是正确的,虽然可能有类型,甚至可能有一点缺陷。
答案 1 :(得分:3)
注意,无法检索std::ifstream
,但可以获取std::istream
。
虽然不是标准C ++的一部分,但有时std::basic_filebuf
会通过constructor which takes 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
以实现所需的工作之外别无他法。