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操作を避けて、で指定された事前に割り当てられたユーザーメモリで動作するようにしQByteArrayます。それは可能ですか?何か良いアイデアはありますか?QDataStreamout

更新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;
    }
    
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)[static]

次のようなものを使用します:

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 に答える