0

我想将 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操作,QByteArrayQDataStreamout. 那可能吗?有什么好主意吗?

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

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

  1. 简单缓冲区.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. 主文件

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

3 回答 3

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)
};
于 2012-04-20T08:20:54.877 回答
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 序列化的任何附加数据。

于 2012-04-07T13:15:39.370 回答
0

为什么不使用QBuffer

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

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

QDataStream out(&buffer);
out << QApplication::palette();
于 2015-07-07T08:41:09.283 回答