Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to convert QByteArray to std::istream or std::ifstream?

I want to create istream from QByteArray at runtime, without saving a physical file in memory of QByteArray.

I found that there are many ways to do the opposite conversion, i.e. istream to QByteArray, but not this one.

How to accomplish that?

like image 803
Sayan Bera Avatar asked Dec 22 '25 03:12

Sayan Bera


1 Answers

To read via std::istringstream from QByteArray seems quite easy:

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

Compiled and tested on cygwin64:

$ qmake-qt5 testQByteArray-istream.pro

$ make

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

$

Done. Stop, wait!

without saving a physical file in memory

I'm not quite sure how to read this. Probably, it means

without copying data saved in QByteArray

I see only two solutions:

  1. Use a QDataStream instead of std::stream. According to doc. QDataStream::QDataStream(const QByteArray &a)

    Constructs a read-only data stream that operates on byte array a.

    This sounds very promising that data is not copied.

  2. DIY. Make a class derived from std::stream which may read from a QByteArray without copying.

Concerning 2. option, I found Dietmar Kühl's answer to SO: Creating an input stream from constant memory. Applying this to the above sample, it would look like this:

#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;
}

Compiled and tested again on cygwin64:

$ qmake-qt5 testQByteArray-istream.pro

$ make

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

$
like image 64
Scheff's Cat Avatar answered Dec 23 '25 16:12

Scheff's Cat



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!