解决此问题的方法称为序列化
序列化是将数据结构或对象状态转换为可以存储(例如,在文件或内存缓冲区中,或通过网络连接链路传输)并稍后在相同或另一个计算机环境中重建的格式的过程。
以下是如何使用 QDataStream 序列化上述结构的完整示例:
// main.cpp
#include <limits>
#include <QDataStream>
#include <QVector>
#include <vector>
typedef struct myStruct
{
int nb_trame;
std::vector<bool> vBool;
std::vector<int> vInt;
std::vector<float> vFloat;
void serialize(QDataStream &out) {
out << nb_trame;
out << QVector<bool>::fromStdVector(vBool);
out << QVector<qint32>::fromStdVector(vInt);
out << QVector<float>::fromStdVector(vFloat);
}
} myStruct;
void fillData(myStruct &s) {
s.nb_trame = 0x42;
s.vBool.push_back(true);
s.vBool.push_back(false);
s.vBool.push_back(false);
s.vBool.push_back(true);
s.vInt.push_back(0xB0);
s.vInt.push_back(0xB1);
s.vInt.push_back(0xB2);
s.vInt.push_back(0xB3);
s.vFloat.push_back(std::numeric_limits<float>::min());
s.vFloat.push_back(0.0);
s.vFloat.push_back(std::numeric_limits<float>::max());
}
int main()
{
myStruct s;
fillData(s);
QByteArray buf;
QDataStream out(&buf, QIODevice::WriteOnly);
s.serialize(out);
}
然后你可以buf
发送QUdpSocket::writeDatagram()
如何QDataStream
序列化
如果我们更换
QByteArray buf;
QDataStream out(&buf, QIODevice::WriteOnly);
和
QFile file("file.dat");
file.open(QIODevice::WriteOnly);
QDataStream out(&file);
序列化的数据被写入文件“file.dat”。这是上面的代码生成的数据:
> hexdump -C file.dat
00000000 00 00 00 42 00 00 00 04 01 00 00 01 00 00 00 04 |...B............|
00000010 00 00 00 b0 00 00 00 b1 00 00 00 b2 00 00 00 b3 |................|
00000020 00 00 00 03 38 10 00 00 00 00 00 00 00 00 00 00 |....8...........|
00000030 00 00 00 00 47 ef ff ff e0 00 00 00 |....G.......|
- 数据以四个字节开始,代表成员 nb_trame (
00 00 00 42
)
- 接下来的八个字节是向量 vBool (
00 00 00 04 01 00 00 01
)
的序列化形式
00 00 00 04
--> 向量中的条目数
01 00 00 01
--> 真、假、假、真
- 接下来的 20 个字节用于 vInt (
00 00 00 04 00 00 00 b0 00 00 00 b1 00 00 00 b2 00 00 00 b3
)
00 00 00 04
--> 向量中的条目数
00 00 00 b0 00 00 00 b1 00 00 00 b2 00 00 00 b3
--> 0xB0、0xB1、0xB2、0xB3(每个条目 4 个字节)
- 接下来的 28 个字节用于 vFloat (
00 00 00 03 38 10 00 00 00 00 00 00 00 00 00 00 00 00 00 00 47 ef ff ff e0 00 00 00
)
00 00 00 03
--> 向量中的条目数
38 10 00 00 00 00 00 00 00 00 00 00 00 00 00 00 47 ef ff ff e0 00 00 00
--> 1.1754943508222875e-38, 0.0, 3.4028234663852886e+38(每个条目8字节)
附加信息(原始发布)
序列化不是一个微不足道的话题,但是那里有很多库可以帮助您。最后,您有两种选择:
- 定义自己的序列化格式
- 使用现有的序列化格式
- 二进制
- 基于文本(例如 JSON、XML)
您选择哪一个在很大程度上取决于您的需求和用例。一般来说,我更喜欢已建立的格式而不是自酿。基于文本的格式本质上不太紧凑,需要更多空间,因此也需要带宽。这是您在决定格式时应该考虑的因素。另一方面,基于文本/人类可读的格式具有更容易调试的优点,因为您可以在文本编辑器中打开它们。还有更多你应该考虑的因素。
序列化之所以有效,是因为您不依赖于机器相关的事物。您唯一需要注意的是序列化数据是一致的并遵循定义的格式。因此,对于序列化数据,您确切地知道字节顺序是如何定义的,特定数据的存储位置等等。
这个想法是发送方序列化数据,通过任何需要的通道发送,接收方再次反序列化数据。数据以哪种格式存储在双方的每一方都无关紧要。
+--------------------------------+ +--------------------------------+
| Host A | | Host B |
| | | |
| | | |
| | | |
| +-------------------------+ | | +-------------------------+ |
| | Raw data | | | | Raw data | |
| |(Specific to plattfrom A)| | | |(Specific to plattfrom B)| |
| +-------------------------+ | | +-------------------------+ |
| | | | ^ |
| | serialize | | | deserialize |
| v | | | |
| +-----------------+ | transmit | +-----------------+ |
| | Serialized Data +----------------------------> Serialized Data | |
| +-----------------+ | | +-----------------+ |
| | | |
+--------------------------------+ +--------------------------------+