StupidBeauty
Read times:221Posted at:Sat Aug 25 02:11:48 2018 - no title specified

Qt5.11开发文档翻译: QDataStream ,QDataStream Class

QDataStream 类,提供了此功能:将二进制数据序列化到某个 QIODevice 中。 详细说明……

头文件:

#include <QDataStream>

qmake指令

QT += core

注意 这个类中的所有函数都是 可重入的

详细说明

QDataStream 类,提供了此功能:将二进制数据序列化到某个 QIODevice 中。

一个数据流,是指一个二进制流,其中包含着编码后的信息。这些信息100%地与主机电脑的操作系统、中央处理器及字节序无关。

妳也可以使用数据流来对 原始 的未编码二进制数据 进行读写。如果妳想要使用一个具有“解析”能力的输入流,那么参考 QTextStream

QDataStream 类,实现了对于C++的基本数据类型的序列化支持,例如 char short int char * 等等。对于更复杂的数据类型的序列化,则是通过将数据分解成基本单元来实现的。

数据流,与 QIODevice 紧密合作。 QIODevice ,代表着某个输入/输出介质,程序可在该介质上读取数据及写入数据。 QFile 类,即是输入/输出设备的一个例子。

示例(向流中写入二进制数据)

QFile file("file.dat");

file.open( QIODevice ::WriteOnly);

QDataStream out(&file);   // 我们会将数据序列化到文件(file)中去

out << QString ("the answer is");   // 序列 化一个字符串

out << ( qint32 )42;        // 序列 化一个整数

示例(从流中读取二进制数据)

QFile file("file.dat");

file.open( QIODevice ::ReadOnly);

QDataStream in(&file);    // 从文件(file)中读取之前序列化的数据

QString str;

qint32 a;

in >> str >> a;           // "the answer is" 42

向流中写入的每个条目,都是以一种预先定义的与该条目的类型相关的二进制格式来写入的。预先支持的Qt类型包括:QBrush QColor QDateTime QFont QPixmap QString QVariant 及狠多其它类型。如想了解所有支持数据流的Qt类型的完整列表,则阅读 Qt数据类型序列

对于整数,最好的处理方式是,在写入时,将它们转换成某个Qt整数类型,而在读取时,也使用相同的Qt整数类型。这样能够确保妳能够得到正确尺寸的整数,并且能够为妳隔离掉编译器和平台的差异。

举个例子,对于一个 char *字符 串,其写入方式是,首先写入一个32位的整数,其值等于该字符串包括末尾'\0'字节的长度,然后写入该字符串的所有字符,包括末尾的'\0'字节。在读取 char *字符串 时,首先读取4个字节,以获取一个32位的长度值,然后读取那么多个字符,以组成这个 char *字符串 ,包括末尾的'\0'字节终止符也会被读入。

最初的输入/输出设备,通常是在构造函数中设置的,不过也可以通过 setDevice ()来改变。如果读取到达了数据的末尾(或者,尚未设置输入/输出设备),则 atEnd ()会返回真(true)。

版本设置

QDataStream 的二进制格式,从Qt 1.0开始就一直在演化,并且,极有可能随着Qt 日后的改变而继续演化。在读取或写入复杂类型时,有一点狠重要,那就是,要确保,在读取及写入时要使用相同版本( version ())的流。如果妳想要保持前向及后向兼容性,那么,可以在程序中将版本号硬编码写入:

stream .setVersion( QDataStream ::Qt_4_0);

如果妳在创造一种新的二进制数据格式,比如说为妳所创造的程序设计一种文件格式,那么,妳就可以利用 QDataStream 来以一种可移植的格式写入数据。一般情况下,妳需要写入一个简短的文件头,其中包含一个版本号,以使得妳在日后能够对该格式进行扩展。例如:

QFile file("file.xxx");

file.open( QIODevice ::WriteOnly);

QDataStream out(&file);

// 写入 一个文件头,其中包含一个“魔数”和一个版本号

out << ( quint32 )0xA0B0C0D0;

out << ( qint32 )123;

out.setVersion( QDataStream ::Qt_4_0);

// 写入数据

out << lots_of_interesting_data;

日后,这样读取:

QFile file("file.xxx");

file.open( QIODevice ::ReadOnly);

QDataStream in(&file);

// 读取 并检查文件头

quint32 magic;

in >> magic;

if (magic != 0xA0B0C0D0)

return XXX_BAD_FILE_FORMAT;

// 读取版本

qint32 version;

in >> version;

if (version < 100)

return XXX_BAD_FILE_TOO_OLD;

if (version > 123)

return XXX_BAD_FILE_TOO_NEW;

if (version <= 110)

in.setVersion( QDataStream ::Qt_3_2);

else

in.setVersion( QDataStream ::Qt_4_0);

// 读取数据

in >> lots_of_interesting_data;

if (version >= 120)

in >> data_new_in_XXX_version_1_2;

in >> other_interesting_data;

妳可以选择,在序列化数据时,使用何种字节序。默认设置是,大端在前(最重要的字节(MSB)在最前面)。将这个选项设置成小端在前的话,会打破可移植性(除非读取的一方也改变成小端在前)。我们建议保持这个默认设置不变,除非妳确实有特殊的需求。

读取及写入原始的二进制数据

妳可以想要直接从数据流中读取/写入妳自己的原始二进制数据。可使用 readRawData ()来从流中将数据读取到一个预先分配好空间的 char * 中去。类似地,可使用 writeRawData ()来向流中写入数据。注意,对于数据的任何编码/解码都必须由妳自己完成。

类似的一对函数是 readBytes ()和 writeBytes ()。这两个函数,与相应的原始( raw )版本不同: readBytes ()会先读入一个quint32,这个值会被用来作为要读取的数据的长度值,然后会读取那么多个字节的数据,放入到预先分配空间的 char * 中去; writeBytes ()会先写入一个quint32,用来 表示数据的长度,然后再写入数据本身。注意,对于数据(除了那个表示长度的quint32 整数之外)本身的编码/解码,必须由妳自己来进行。

读取及写入Qt的集合类

Qt中的那些容器类,也可以被序列化到 QDataStream 中去。这包括: QList QLinkedList QVector QSet QHash QMap 。对应的流式操作符,被声明为那些类的非成员函数。

读取及写入其它的Qt 类

除了此处说明的那些重载的流式操作符之外,任何一个妳想要序列化到 QDataStream 中去的Qt 类,都会具有对应的流式操作符,被声明为该类的非成员函数:

QDataStream &operator<<( QDataStream &, const QXxx &);

QDataStream &operator>>( QDataStream &, QXxx &);

例如,此处展示的是,被声明为 QImage 类的非成员函数的流式操作符:

QDataStream & operator<< ( QDataStream & stream, const QImage & image);

QDataStream & operator>> ( QDataStream & stream, QImage & image);

要想确认妳最喜爱的Qt 类是否定义有类似的流式操作符的话,则查看那个类的文档中的 相关非成员函数 小节。

使用读取事务

在使用数据流来对某个异步设备进行操作时,对应的数据块可能在任何时间点到来。 QDataStream 类实现了一种事务机制,它提供了这种能力:使用一系列的流操作来原子式地读取数据。例如,妳可以在一个连接到readyRead()信号的槽中使用事务来处理来自套接字的不完整数据读取:

in .startTransaction();

QString str;

qint32 a;

in >> str >> a; // 尝试原子 式地读取数据包

if (!in.commitTransaction())

return;     // 等待更多数据

如果没有收到完整的数据包,那么,这砣代码会将流恢复到它的初始位置,然后,妳就需要等待更多数据的到来。

参考 QTextStream QVariant

成员类型文档

enum QDataStream:: ByteOrder

用于读取/写入数据的字节序。

常量

说明

QDataStream::BigEndian

QSysInfo::BigEndian

最重要的字节在最前(默认)

QDataStream::LittleEndian

QSysInfo::LittleEndian

最不重要的字节在最前

enum QDataStream:: FloatingPointPrecision

在读取/写入数据时使用的浮点数精度。只有当数据流的版本大于或等于 Qt_4_6 时才有效。

警告:对于分别写入和读取该数据流的两个对象,其使用的浮点数精度必须是相同值。

常量

说明

QDataStream::SinglePrecision

0

这个数据流中的所有浮点数都具有32位精度。

QDataStream::DoublePrecision

1

这个数据流中的所有浮点数都具有64位精度。

参考 setFloatingPointPrecision () floatingPointPrecision ()

enum QDataStream:: Status

这个枚举,描述了数据流当前的状态。

常量

说明

QDataStream::Ok

0

这个数据流当前工作正常。

QDataStream::ReadPastEnd

1

这个数据流在读取过程中已经越过了底层设备的数据末尾了。

QDataStream::ReadCorruptData

2

这个数据流读取到了破损的数据。

QDataStream::WriteFailed

3

这个数据流无法向底层设备写入数据。

enum QDataStream:: Version

这个枚举,提供了对于历史上的数据序列化格式版本号的符号简写。

常量

说明

QDataStream::Qt_1_0

1

版本1 (Qt 1.x)

QDataStream::Qt_2_0

2

版本2 (Qt 2.0)

QDataStream::Qt_2_1

3

版本3 (Qt 2.12.22.3)

QDataStream::Qt_3_0

4

版本4 (Qt 3.0)

QDataStream::Qt_3_1

5

版本5 (Qt 3.13.2)

QDataStream::Qt_3_3

6

版本6 (Qt 3.3)

QDataStream::Qt_4_0

7

版本7 (Qt 4.0Qt 4.1)

QDataStream::Qt_4_1

Qt_4_0

版本7 (Qt 4.0Qt 4.1)

QDataStream::Qt_4_2

8

版本8 (Qt 4.2)

QDataStream::Qt_4_3

9

版本9 (Qt 4.3)

QDataStream::Qt_4_4

10

版本10 (Qt 4.4)

QDataStream::Qt_4_5

11

版本11 (Qt 4.5)

QDataStream::Qt_4_6

12

版本12 (Qt 4.6Qt 4.7Qt 4.8)

QDataStream::Qt_4_7

Qt_4_6

Qt_4_6相同

QDataStream::Qt_4_8

Qt_4_7

Qt_4_6相同

QDataStream::Qt_4_9

Qt_4_8

Qt_4_6相同

QDataStream::Qt_5_0

13

版本13 (Qt 5.0)

QDataStream::Qt_5_1

14

版本14 (Qt 5.1)

QDataStream::Qt_5_2

15

版本15 (Qt 5.2)

QDataStream::Qt_5_3

Qt_5_2

Qt_5_2相同

QDataStream::Qt_5_4

16

版本16 (Qt 5.4)

QDataStream::Qt_5_5

Qt_5_4

Qt_5_4相同

QDataStream::Qt_5_6

17

版本17 (Qt 5.6)

QDataStream::Qt_5_7

Qt_5_6

Qt_5_6相同

QDataStream::Qt_5_8

Qt_5_7

Qt_5_6相同

QDataStream::Qt_5_9

Qt_5_8

Qt_5_6相同

QDataStream::Qt_5_10

Qt_5_9

Qt_5_6相同

QDataStream::Qt_5_11

Qt_5_10

Qt_5_6相同

参考 setVersion () version ()

成员函数文档

void QDataStream:: abortTransaction ()

放弃一次读取事务。

这个函数,用于在高层协议出错或者流同步出错时丢弃事务。

如果是在某个内层事务上调用这个方法,则会导致事务的放弃行为被向上传递到最外层的事务上去,并且,后续启动的内层事务会被强制失败。

对于最外层的事务,会丢弃掉恢复点以及内部为该个流复制的任何数据。不会影响到流的当前读取位置。

会将数据流的状态设置成

常量

说明

ReadCorruptData

这个函数是从Qt 5.7 开始引入的。

参考 startTransaction () commitTransaction () rollbackTransaction ()

QDataStream::ByteOrder QDataStream:: byteOrder () const

返回当前设置的字节序 -- 其值是 BigEndian LittleEndian

参考 setByteOrder ()

bool QDataStream:: commitTransaction ()

完成一个读取事务。如果在该事务过程中未发生任何错误,则返回真( true );否则返回假( false )。

如果是在某个内层事务上调用这个方法,那么,提交动作会被后延,直到在最外层的事务上调用了commitTransaction()、 rollbackTransaction ()或 abortTransaction ()为止。

否则,如果流的状态表明读取动作已经越过了数据的末尾,那么,这个函数会将流的数据恢复到发起 startTransaction ()调用时的位置。如果发生了这种情况,那么,妳就需要等待更多数据的到来,然后再启动一个新的事务。如果数据流读取到了破损的数据,或者任何一个内层事务被放弃了,那么,这个函数会放弃掉事务。

这个函数是从Qt 5.7 开始引入的。

参考 startTransaction () rollbackTransaction () abortTransaction ()

QDataStream::FloatingPointPrecision QDataStream:: floatingPointPrecision () const

返回这个数据流的浮点数精度。

这个函数是从Qt 4.6 开始引入的。

参考 FloatingPointPrecision setFloatingPointPrecision ()

QDataStream &QDataStream:: readBytes ( char *& s , uint & l )

从流中读取内容到缓冲区 s ,并且返回这个流的引用。

此处的缓冲区 s ,是使用 new [] 来分配空间的。日后,妳需要使用 delete [] 操作符来销毁它。

l参数,会被设置成缓冲区的长度。如果读取的字符串是空白的,那么 l 会被设置成0,并且 s 会被设置成空指针。

具体的序列化格式是,一个quint32的长度值,然后是 l 个字节的数据。

参考 readRawData () writeBytes ()

int QDataStream:: readRawData ( char * s , int len )

从流中向 s 中读取最多 len 个字节的数据,并且返回实际读取的字节数。如果发生了错误,那么这个函数会返回-1。

缓冲 s 必须预先分配空间。数据 并未 被编码。

参考 readBytes () QIODevice::read () writeRawData ()

void QDataStream:: rollbackTransaction ()

将某个读取事务还原。

这个函数,通常用于,在提交事务之前,如果检测到发生了不完整的读取操作,则对事务进行回滚。

如果在某个内层事务上调用这个函数,那么,还原动作会一直传播到最外层的事务,并且,后续启动的内层事务会强制失败。

对于最外层的事务,会将流中的数据恢复到发生 startTransaction ()调用时的位置。如果在数据流中已经读取到了破损的数据,或者,任何一个内层事务被放弃了,那么,这个函数会放弃掉该事务。

如果之前的流操作是成功了,那么,会将数据流的状态设置成

常量

说明

ReadPastEnd

这个函数是从Qt 5.7 开始引入的。

参考 startTransaction () commitTransaction () abortTransaction ()

void QDataStream:: setByteOrder ( QDataStream::ByteOrder bo )

将序列化的字节序设置为 bo

此处 bo参数,可以是 QDataStream::BigEndian QDataStream::LittleEndian

默认设置是大端在前。我们建议不要改动这个选项,除非妳确实有特殊的需求。

参考 byteOrder ()

void QDataStream:: setFloatingPointPrecision ( QDataStream::FloatingPointPrecision precision )

将这个数据流的浮点数精度设置成 precision 。如果浮点数精度是 DoublePrecision ,并且数据流的版本号是 Qt_4_6 或更高,那么,所有的浮点数,在写入和读取时,都会使用64 位的精度。如果浮点数精度是 SinglePrecision ,并且数据流的版本号是 Qt_4_6 或更高,那么,所有的浮点数,在写入和读取时,都会使用32 位的精度。

对于 Qt_4_6 之前的版本,数据流中所使用的浮点数的精度,取决于具体调用的流操作符。

默认值是 DoublePrecision

注意,这个属性,并不会影响到对于 qfloat16 实例的序列化和反序列化。

警告: 这个属性,对于用于写入和读取该个数据流的对象,都必须设置成相同的值。

这个函数是从Qt 4.6 开始引入的。

参考 floatingPointPrecision ()

void QDataStream:: setVersion ( int v )

将数据序列化格式的版本号设置成 v ,它是 Version 枚举中的一个值。

如果妳正在使用的是 Qt 的当前版本,那么,妳并不是 必须 设置版本号,然而,对于妳自定义的二进 制格式,我们建议妳要设置版本号;参考详细说明中的 版本

为了支持新的功能,在某些Qt 版本中,某些Qt 类的数据流序列化格式会发生变化。如果妳想要读取由较旧版本的Qt 创建的数据,或者,想写入能够被那些与较旧版本的Qt 编译到一起的程序读取的数据,那么,就应当使用这个函数来修改 QDataStream 所使用的序列化格式。

Version 枚举,提供了针对不同版本的Qt 所使用的符号常量。例如:

QDataStream out(file);

out.setVersion( QDataStream ::Qt_4_0);

参考 version () Version

int QDataStream:: skipRawData ( int len )

从设备中跳过 len 个字节的数据。返回实际跳过的字节个数,如果出错,则返回-1。

这个函数,等价于,针对某个长度为 len 的缓冲区调用 readRawData (),并且忽略掉该个缓冲区。

这个函数是从Qt 4.1 开始引入的。

参考 QIODevice::seek ()

void QDataStream:: startTransaction ()

在这个流上启动一个新的读取事务。

在读取操作中,定义一个可恢复的位置。对于串行设备,读取到的数据会在内部进行复制,以便在发生不完整读取时进行恢复。对于随机访问设备,这个函数会记录流中的当前位置。调用 commitTransaction () rollbackTransaction () abortTransaction ()来结束当前事务。

一旦启动了某个事务,后续再调用这个函数的话,会使得该个事务成为递归的。内层事务会充当最外层事务的代理(也就是说,向最外层事务报告读取操作的状态,使得最外层事务能够恢复流的位置)

注意 不支持恢复到由嵌套的startTransaction()调用所记录的位置。

如果在某个事务中发生了错误(包括内层事务失败),那么,从该个数据流中读取数据的操作会被制止(后续的读取操作都会返回空白/零值),并且,后续的内层事务会被强制失败。再启动一个新的最外层 事务,就会从这种状态下恢复。这种行为,使得,不需要单独为每次读取操作进行错误检查。

这个函数是从Qt 5.7 开始引入的。

参考 commitTransaction () rollbackTransaction () abortTransaction ()

QDataStream::Status QDataStream:: status () const

返回数据流的状态。

参考 Status setStatus () resetStatus ()

int QDataStream:: version () const

返回当前的数据序列化格式的版本号码。

参考 setVersion () Version

QDataStream &QDataStream:: writeBytes (const char * s , uint len )

将长度值 len 和缓冲区 s 的内容写入到流中,并且返回这个流的引用。

len 会被序列化为一个quint32,其后是来自于 s len 个字节。注意,数据并 不会 被编码。

参考 writeRawData () readBytes ()

int QDataStream:: writeRawData (const char * s , int len )

s 中的 len 个字节数据写入到流中。返回实际写入的字节数,如果出错,则返回-1。数据并 不会 被编码。

参考 writeBytes () QIODevice::write () readRawData ()

知美人

未知美人

Your opinions
Your name:Email:Website url:Opinion content:
- no title specified

女神相机:在女神不知情的情况下,为她拍出最自然的玉照

 
??Like this article? Give us some tips.??