外部存储器上的QDataStream?

时间:2012-04-07 03:57:25

标签: c++ qt

我想将QVector序列化为char *数组。我通过以下代码执行此操作:

QVector<int> in;
...
QByteArray bytes;
QDataStream stream(&bytes, QIODevice::WriteOnly);
stream << in;
std::copy(bytes.constData(), bytes.constData() + bytes.size(), out);

我保证out足够大。由于我经常调用此代码,因此我希望避免这种不必要的std::copy操作,并使QByteArrayQDataStream处理由out指向的预分配用户内存。那可能吗?有什么好主意吗?

UPDATE QByteArray :: fromRawData()与需求不匹配,因为它不允许更改创建的char *缓冲区,换句话说, QByteArray在首次修改此类创建的实例时执行深层复制。 正如他们所说。 这确保了QByteArray永远不会修改原始数据数组本身。

解决方案:@skyhisi提出的解决方案完全符合我的需求。完整的代码如下。

  1. SimpleBuffer.hpp

    #pragma once
    #include <QtCore/QIODevice>
    
    class SimpleBuffer : public QIODevice {
      Q_OBJECT
      Q_DISABLE_COPY(SimpleBuffer)
    
    public:
      SimpleBuffer(char* const begin, const char* const end) :
        _begin(begin),
        _end(end){}
    
      virtual bool atEnd() const {
        return _end == _begin;
      }
    
      virtual bool isSequential() const {
        return true;
      }
    
    protected:
      virtual qint64 readData(char*, qint64) {
        return -1;
      }
    
      virtual qint64 writeData(const char* const data, const qint64 maxSize) {
        const qint64 space = _end - _begin;
        const qint64 toWrite = qMin(maxSize, space);
        memcpy(_begin, data, size_t(toWrite));
        _begin += toWrite;
        return toWrite;
      }
    
    private:
      char* _begin;
      const char* const _end;
    };
    
  2. 的main.cpp

    #include "SimpleBuffer.hpp"
    #include <QtCore/QVector>
    #include <QtCore/QDataStream>
    #include <QtCore/QByteArray>
    
    int main(int, char**) {
      QVector<int> src;
      src << 3 << 7 << 13 << 42 << 100500;
      const size_t dataSize = sizeof(quint32) + src.size() * sizeof(int);
      char* const data = new char[dataSize];
    
      // prepare stream and write out the src vector
      {
        SimpleBuffer simpleBuffer(data, data + dataSize);
        simpleBuffer.open(QIODevice::WriteOnly);
        QDataStream os(&simpleBuffer);
        os << src;
      }
    
      // read vector with QByteArray
      QVector<int> dst;
      {
        const QByteArray byteArray = QByteArray::fromRawData((char*)data, dataSize);
        QDataStream is(byteArray);
        is >> dst;
      }
      delete [] data;
    
      // check we've read exactly what we wrote
      Q_ASSERT(src == dst);
    
      return 0;
    }
    

3 个答案:

答案 0 :(得分:2)

我认为您可能需要实现QIODevice,您可以非常轻松地制作一个非常简单的顺序设备。这是我快速拼凑的一个,我没有检查它的工作原理(随意让它工作并编辑帖子)。

class SimpleBuffer : public QIODevice
{
    Q_OBJECT
    public:
        SimpleBuffer(char* begin, char* end):mBegin(begin),mEnd(end){}

        virtual bool atEnd() const {return mEnd == mBegin; }

        virtual bool isSequential() const { return true; }

    protected:
        virtual qint64 readData(char*, qint64) { return -1; }

        virtual qint64 writeData(const char* data, qint64 maxSize)
        {
            const qint64 space = mEnd - mBegin;
            const qint64 toWrite = qMin(maxSize, space);
            memcpy(mBegin, data, size_t(toWrite));
            mBegin += toWrite;
            return toWrite;
        }

   private:
        char* mBegin;
        char* mEnd;

        Q_DISABLE_COPY(SimpleBuffer)
};

答案 1 :(得分:0)

也许fromRawData工作:

QByteArray QByteArray :: fromRawData(const char * data,int size)[静态]

使用类似的东西:

char* out=new char[enoughbytes]; // preallocate at suitable scope
QVector<int> in; 
QByteArray ba=QByteArray::fromRawData(out,enoughbytes); 
QDataStream stream(&ba,QIODevice::WriteOnly); 
stream << in;

请注意,QDataStream会在数据开头添加一些自己的数据(虽然不多),所以请记住预先分配更多,以及QVector序列化的其他数据。

答案 2 :(得分:0)

为什么不使用QBuffer

QByteArray myBuffer;
myBuffer.reserve(10000); // no re-allocation

QBuffer buffer(&myBuffer);
buffer.open(QIODevice::WriteOnly);

QDataStream out(&buffer);
out << QApplication::palette();