Десериализация необработанных данных с использованием 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
так далее.)