如何将QByteArray转换为std::istream或std::ifstream?

3
我希望能在运行时从 QByteArray 创建 istream,而不需要将 QByteArray 保存到物理文件中。
我发现有很多方法可以进行相反的转换,即 istream 转为 QByteArray,但没有这种方法。
如何实现?

1
如果使用带有过滤I/O流的Boost,这个问题就相对“容易”了,但是需要阅读相当难懂的文档,代码量也会增加200多行。另一个选择是从头编写自己的过滤istream,这也是非常麻烦的(我自己已经做过很多次了,IO流可能是C++标准中最糟糕的部分)。更简单的方法是通过重载operator<<operator>>,将QByteArray转换为istream和ostream。 - Alex Huszagh
1个回答

5
使用std::istringstreamQByteArray读取似乎非常简单: 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 读取。

关于第二个选项,我发现 Dietmar Kühl 对 SO: Creating an input stream from constant memory 的回答。将其应用到上面的示例中,它会像这样:

#include <iostream>
#include <QtCore>

// borrowed from https://dev59.com/NWcs5IYBdhLWcg3wMhCz#13059195
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.'

$

1
谢谢...我需要时间去仔细研究解决方案..然后让你知道。 - Sayan Bera

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接