QDataStream

关注
义项:Qt 二进制数据序列化类
QDataStream

QDataStream是Qt框架提供的二进制数据序列化类,用于把C++与Qt的数据类型以预定义的二进制格式写入或读出QIODevice。它的编码结果与宿主计算机的操作系统、CPU和字节序无关,因此在一台机器上写出的数据流可以由另一种平台上的程序读取。QDataStream常用于自定义文件格式、网络协议报文和进程间数据交换,并配套提供字节序、浮点精度与序列化格式版本等控制手段。

百科 图文
目录
  1. 定义
  2. 原理
  3. 发展历程
  4. 应用
  5. 局限
  6. 参见

定义

QDataStream是Qt框架核心模块中的一个类,作用是按照预定义的二进制格式把数据序列化到QIODevice,或者从其中反序列化回来[1]。它实现的是C++基本类型如char、short、int、char*等的序列化,较复杂的数据则通过拆解成基本单元来完成[2]。

该类支持的不只是基本类型,还包括QBrush、QColor、QDateTime、QFont、QPixmap、QString、QVariant等Qt类型,以及QList、QSet、QHash、QMap等容器类型[3]。写入流中的每一项都按与该项类型对应的固定二进制格式记录[4]。

官方文档说明,QDataStream中的所有函数都是可重入的[1]。使用方式以运算符重载为基础,写出用<<,读入用>>,二者返回数据流自身的引用,因而可以连续书写[2]。

原理

数据流与QIODevice紧密配合:QIODevice代表可读写的输入输出介质,QFile是其中一例[2]。构造函数可以直接接收一个设备指针,也可以在无设备的情况下先构造对象,再用setDevice()指定设备;若无设备或已读到数据末尾,atEnd()返回真[2]。构造在QByteArray上操作的数据流时,内部会创建一个QBuffer来包装该字节数组[3]。

整数按固定位宽写出,还会按设定的字节序决定字节排列。默认字节序为大端,即最高有效字节优先;改成小端会破坏可移植性,除非读取端也作相同设置[3]。浮点数使用IEEE 754格式写出,读取端与写入端的浮点精度需要设置成同一个值[5]。

字符串与容器的格式是长度说明符在前、数据在后[4]。以char*字符串为例,先写一个32位整数表示长度(含结尾的\0字节),随后写出全部字符(也含\0);读取时先读4个字节取得长度,再按该长度读入字符[2]。当元素数量很大时,会先写出扩展标记0xfffffffe,再跟随一个64位整数给出真实长度[4]。

除已编码的格式外,还可以用readRawData()与writeRawData()直接读写未编码的原始二进制数据,缓冲区需由调用者预先分配[2]。readBytes()与writeBytes()则在此基础上增加一个quint32长度前缀,其余编解码工作仍由使用者自行完成[2]。

发展历程

QDataStream的二进制格式自Qt 1.0以来一直在演进,并且预计会随Qt的变化继续调整[4]。其Version枚举用符号名对应不同的格式版本号,例如Qt_1_0对应版本1、Qt_2_0对应版本2、Qt_3_0对应版本4、Qt_4_0对应版本7、Qt_5_0对应版本13、Qt_6_0对应版本20,后续版本多数沿用前一版本的格式[5]。

读取和写出复杂类型时,两端必须使用同一个流版本,否则无法正确还原[4]。需要同时满足向前与向后兼容时,可以在程序中把版本号写死,例如调用setVersion()指定具体的Qt版本常量[1]。

浮点精度控制由setFloatingPointPrecision()提供,该函数在Qt 4.6引入;当数据流版本为Qt_4_6或更高时它才起作用,默认值为双精度[5]。读取事务机制startTransaction()、commitTransaction()、rollbackTransaction()与abortTransaction()在Qt 5.7加入,用于在异步设备上把一组读操作当作原子操作处理[6]。

应用

最典型的用途是自定义文件格式:把数据以可移植的二进制形式写入文件,通常在开头写入一个含魔术字符串和版本号的头部,为以后扩展留出空间[4]。Qt自身的一些类通过声明为非成员的流运算符支持序列化,QImage即是一例;要确认某个类是否支持,可以查看其文档页面中的相关非成员部分[3]。

自定义类型要接入数据流,需要以全局方式重载<<与>>运算符,在运算符内部把对象的各成员依次写入或读出,顺序在读写两端必须一致[6]。枚举类型无需手动定义流运算符即可序列化,枚举类按其声明的大小写出[3]。

在异步设备上操作时,数据块可能在任何时刻到达,事务机制允许用一串流操作符原子地读取数据[3]。典型写法是在处理readyRead()信号的槽里启动事务,若commitTransaction()返回失败,则说明数据包不完整,流会回到起始位置,等待后续数据[3]。

局限

官方文档指出,QDataStream对损坏的输入不具备抵御能力,即使使用事务也不应把它用于安全敏感的场景[3]。事务能帮助判断当前可用的数据能否解出一个有效输入,但它假定已有的数据本身格式正确[3]。

许多反序列化运算符会依据流中读到的信息分配内存,而不会校验申请的内存量是否合理,也不会校验其与流中实际可用的数据量是否匹配;例如反序列化QByteArray或QString时,可能遇到要求分配数吉字节内存的情形[3]。因此它不应用于来源不可信的内容,程序应只解码可信来源的数据流[3]。

状态枚举记录了运行中的异常,包括读取越过底层数据末尾的ReadPastEnd、读到损坏数据的ReadCorruptData、无法写入设备的WriteFailed,以及因超出当前平台支持范围而失败的SizeLimitExceeded[5]。

另外,字节序与浮点精度这类设置必须在读写两端保持一致,否则解析结果会出错;把默认的大端改为小端也会牺牲可移植性[3]。

参见

  • Qt —— QDataStream所属的跨平台应用程序开发框架。

  • QIODevice —— 数据流读写的输入输出设备抽象,QFile等均继承自它。

  • JSON —— 另一种常见的数据序列化格式,以文本形式表达结构化数据。

  • 字节序 —— 决定多字节整数在内存与流中字节排列顺序的规则。

  • 序列化 —— 把对象状态转换为可存储或可传输形式的一般过程。

参考资料

  1. QDataStream类 [引用日期2026-10-14]
  2. manpages.org 上的网页 [引用日期2026-10-14]
  3. 概述 - Qt for Python [引用日期2026-10-14]
  4. QDataStream Class [引用日期2026-10-14]
  5. QDataStream Class Reference | Документация Qt [引用日期2026-10-14]
  6. Qt5.10 GUI完全参考手册(PDF) [引用日期2026-10-14]
词条评价
词条统计

浏览次数:2 次

阅读量:0 次 · 阅读完成量:0 次

最近更新:2026-10-13T19:29:43Z

历史版本

本条目引用的词条
QIODevice Qt 容器 JSON 字节序 序列化