Десериализация необработанных данных с использованием QDataStream

У меня есть данные, которые поступают из сокета TCP как необработанные данные (у меня есть указанный формат), а затем создать объект на основе этих данных. Формат такой: 24 байта заголовка [размер данных и некоторая другая информация], а затем объем данных, указанный в заголовке.

Я хотел бы просто прочитать его как объект (объект имеет буфер для данных внутри с динамическим размером, куда помещаются данные). Можно ли как-то переопределить QDataStream или сделать какой-то другой способ элегантно обернуть его? Я хотел бы воспользоваться методами транзакций для чтения целых пакетов данных и не заботиться о сборке их, если они разбиты на части (половину заголовка или просто не полный объем данных).

В общем, я хотел бы сделать что-то вроде этого:

Event event;          // my custom class
QDataStream dataStream(tcpSocket);

dataStream >> event;
dataStream.commit();

1 ответ

Я считаю, что это случай перегрузки оператора. Я сделал небольшой наглядный пример:

class Test
{
public:
    int i;
    float f;
    double d;

    char empty[4];
    int ii[3];

    QString s;

public:
    friend QDataStream& operator>>(QDataStream& in, Test& test);
    friend QDataStream& operator<<(QDataStream& out, const Test& test);
};

QDataStream& operator>>(QDataStream& in, Test& test)
{
    in >> test.i;

    in.setFloatingPointPrecision(QDataStream::SinglePrecision);
    in >> test.f;

    in.setFloatingPointPrecision(QDataStream::DoublePrecision);
    in >> test.d;

    in.skipRawData(sizeof test.empty);
    in.readRawData(reinterpret_cast<char*>(test.ii), sizeof test.ii);

    in >> test.s;

    return in;
}

QDataStream& operator<<(QDataStream& out, const Test& test)
{
    out << test.i;

    out.setFloatingPointPrecision(QDataStream::SinglePrecision);
    out << test.f;

    out.setFloatingPointPrecision(QDataStream::DoublePrecision);
    out << test.d;

    out.writeRawData(reinterpret_cast<const char*>(test.empty), sizeof test.empty);
    out.writeRawData(reinterpret_cast<const char*>(test.ii), sizeof test.ii);
    out << test.s;

    return out;
}

Тогда вы можете сделать:

 outputStream
        << test1
        << test2
        << test3;

// ...

inputStream.startTransaction();
inputStream
        >> test11
        >> test22
        >> test33;
inputStream.commitTransaction();

Также эти операторы предопределены для фундаментальных контейнеров Qt (QVector, QList, QSet так далее.)

Другие вопросы по тегам