Как преобразовать QByteArray в std :: istream или std :: ifstream? - PullRequest
0 голосов
/ 25 сентября 2018

Я хочу создать istream из QByteArray во время выполнения, не сохраняя физический файл в памяти QByteArray.

Я обнаружил, что существует много способов сделать обратное преобразование, например istream до QByteArray, но не этот.

Как это сделать?

1 Ответ

0 голосов
/ 25 сентября 2018

Чтение через std::istringstream из QByteArray кажется довольно простым:

testQByteArray-istream.cc:

#include <iostream>
#include <sstream>
#include <QtCore>

int main()
{
  qDebug() << "Qt Version:" << QT_VERSION_STR;
  // make a QByteArray
  QByteArray data("Hello Qt World.");
  // convert to std::string
  std::istringstream in(data.toStdString());
  // read from istringstream
  for (;;) {
    std::string buffer;
    if (!std::getline(in, buffer)) break;
    std::cout << "Got: '" << buffer << "'\n";
  }
  // done
  return 0;
}

testQByteArray-istream.pro:

SOURCES = testQByteArray-istream.cc

QT = core

Скомпилированои протестировано на cygwin64 :

$ qmake-qt5 testQByteArray-istream.pro

$ make

$ ./testQByteArray-istream 
Qt Version: 5.9.4
Got: 'Hello Qt World.'

$

Готово.Стоп, подождите!

без сохранения физического файла в памяти

Я не совсем уверен, как это прочитать.Вероятно, это означает

без копирования данных, сохраненных в QByteArray

Я вижу только два решения:

  1. ИспользованиеQDataStream вместо std::stream.Согласно док.QDataStream::QDataStream(const QByteArray &a)

    Создает поток данных только для чтения, который работает с байтовым массивом a.

    Звучит очень обещая, что данные не копируются.

  2. DIY.Создайте класс, полученный из std::stream, который может читать из QByteArray без копирования.

Относительно 2. Я нашел ответ Дитмара Кюля на SO: Создание вводапоток из постоянной памяти .Если применить это к приведенному выше примеру, это будет выглядеть так:

#include <iostream>
#include <QtCore>

// borrowed from https://stackoverflow.com/a/13059195/7478597
struct membuf: std::streambuf {
  membuf(char const* base, size_t size) {
    char* p(const_cast<char*>(base));
    this->setg(p, p, p + size);
  }
};
struct imemstream: virtual membuf, std::istream {
  imemstream(char const *base, size_t size):
    membuf(base, size),
    std::istream(static_cast<std::streambuf*>(this)) {
  }
};

int main()
{
  qDebug() << "Qt Version:" << QT_VERSION_STR;
  // make a QByteArray
  QByteArray data("Hello Qt World.");  
  imemstream in(data.data(), (size_t)data.size());
  // read from istringstream
  for (;;) {
    std::string buffer;
    if (!std::getline(in, buffer)) break;
    std::cout << "Got: '" << buffer << "'\n";
  }
  // done
  return 0;
}

Скомпилировано и протестировано снова на cygwin64 :

$ qmake-qt5 testQByteArray-istream.pro

$ make

$ ./testQByteArray-istream 
Qt Version: 5.9.4
Got: 'Hello Qt World.'

$
...