QDataStream类的官方简介

16 篇文章 2 订阅

数据流是编码信息的二进制流,它与主机计算机的操作系统,CPU或字节顺序无关。 例如,运行Windows的Sun SPARC可以读取Windows下PC写入的数据流。

您还可以使用数据流来读取/写入未编码的原始二进制数据。 如果要“解析”输入流,请参见QTextStream。

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

数据流与QIODevice紧密协作。 QIODevice表示一种输入/输出介质,可以从中读取数据或将数据写入其中。 QFile类是I/O设备的示例。
示例(将二进制数据写入流):

QFile file("file.dat");
file.open(QIODevice::WriteOnly);
QDataStream out(&file);   // we will serialize the data into the file
out << QString("the answer is");   // serialize a string
out << (qint32)42;        // serialize an integer

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

QFile file("file.dat");
file.open(QIODevice::ReadOnly);
QDataStream in(&file);    // read the data serialized from the file
QString str;
qint32 a;
in >> str >> a;           // extract "the answer is" and 42

写入流的每个项目均以预定义的二进制格式写入,该格式根据项目的类型而有所不同。支持的Qt类型包括QBrush,QColor,QDateTime,QFont,QPixmap,QString,QVariant等。有关支持数据流的所有Qt类型的完整列表,请参见序列化Qt数据类型

对于整数,最好始终将其转换为Qt整数类型进行写入,然后再读回相同的Qt整数类型。这样可以确保获得所需大小的整数,并使您与编译器和平台的差异隔离。

枚举可以通过QDataStream进行序列化,而无需手动定义流运算符。枚举类使用声明的大小进行序列化。
举一个例子,一个char *字符串被写为一个32位整数,该整数等于包括'\0'字节的字符串的长度,其后是包括'\0'字节的字符串的所有字符。读取char *字符串时,将读取4个字节以创建32位长度值,然后读取char *字符串的许多字符,包括'\0'终止符。

初始I/O设备通常在构造函数中设置,但可以使用setDevice()进行更改。如果到达数据末尾(或没有设置I/O设备),则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);

  // Write a header with a "magic number" and a version
  out << (quint32)0xA0B0C0D0;
  out << (qint32)123;

  out.setVersion(QDataStream::Qt_4_0);

  // Write the data
  out << lots_of_interesting_data;

然后阅读:

  QFile file("file.xxx");
  file.open(QIODevice::ReadOnly);
  QDataStream in(&file);

  // Read and check the header
  quint32 magic;
  in >> magic;
  if (magic != 0xA0B0C0D0)
      return XXX_BAD_FILE_FORMAT;

  // Read the version
  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);

  // Read the data
  in >> lots_of_interesting_data;
  if (version >= 120)
      in >> data_new_in_XXX_version_1_2;
  in >> other_interesting_data;

您可以选择序列化数据时要使用的字节顺序。默认设置为big endian(MSB在前)。将其更改为Little Endian会破坏可移植性(除非读者也更改为Little Endian)。除非您有特殊要求,否则我们建议保留此设置。

读写原始二进制数据

您可能希望直接从数据流读取/写入自己的原始二进制数据。可以使用readRawData()将数据从流中读取到预分配的char *中。同样,可以使用writeRawData()将数据写入流中。请注意,数据的任何编码/解码都必须由您完成。

一对类似的函数是readBytes()和writeBytes()。它们与原始副本不同,如下所示: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; // try to read packet atomically

  if (!in.commitTransaction())
      return;     // wait for more data

如果没有收到完整的数据包,此代码会将流恢复到初始位置,此后您需要等待更多数据到达。

  • 1
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值