Я кодирую проект Android с компонентом NDK C ++, и у меня есть файл, который нуждается в большом разборе. NDK позволяет мне только получить указатель FILE * на файл, с которым я имею дело, а не ifstream, с которым связано еще несколько вспомогательных функций. Есть ли способ конвертировать FILE * (cstdio) в ifstream (iostream)?
В общем, вы можете не преобразовать 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);
Я просто набрал код выше и в настоящее время не могу его опробовать. Тем не менее, основные должны быть правильными, хотя могут быть типы и, возможно, даже небольшой недостаток.
Обратите внимание, что нет способа получить 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
который реализует требуемую работу.