最佳实践:如何解释/处理QDataStream?

时间:2013-04-15 11:39:54

标签: c++ qt serialization qbytearray

我需要处理由另一个非Qt程序创建的已定义结构的流式二进制数据(QDataStream)。我想知道解释这些数据的最佳做法是什么。假设数据在电报中的结构(提供结构定义)如下,并且不能由我自己更改:

4字节标题| 2字节序列号| 1字节校验和| 10字节数据

我看到以下可能性来处理“Telegram”类中的数据:

  1. Telegram类具有私有QByteArray成员变量。使用readRawData方法从流中一次读取所有数据(17个字节)并存储在那里。使用公共方法(如序列号return (array.at(4)<<8) + array.at(5))访问和解释变量,但不是很优雅。
  2. Telegram类具有与struct结合的公共char [17]成员变量。使用readRawData从流中读取所有数据并将其存储在那里。在访问变量之后,这只在结构上完成,如telegramstruct.squenceNumber我看到这个方法的潜在问题,如字节顺序和填充。
  3. Telegram类具有每个电报字段的私有成员变量,如QString strHeader。从流中读取报文时,数据直接存储在这些变量中。使用readRawData或使用运算符&gt;&gt;完成读取。对于基本类型。
  4. 代码应该尽可能快,因为要处理大量数据。我在Windows上使用Qt 5.0.1和MinGW。

    我的问题:

    • 上述哪种解决方案最佳实践且速度快,还是有更好的方法?
    • 一次读取比读取4个字节,2个字节,1个字节,...更快,就像在3中一样?
    • 使用1和3,我不能使用带有已定义结构的提供的头文件,这是不好的做法吗?
    • 在某种程度上可能与QByteArray和结构有一种“联合”吗?
    • 如何使用解决方案3轻松计算校验和?

    非常感谢您的意见和提示。

    克里斯

1 个答案:

答案 0 :(得分:2)

好吧,抱歉没有那么多时间编写代码示例,但会尝试给出一个简短的提示。 1)性能问题。一旦你有性能限制,首先要优化的是来自数据来源的流的实际读取量。无论是文件/插座/等,无论如何都是QIODevice。因此,首先要做的是维护某种QByteArray,在每个准备好的尝试/处理数据接收通知中添加QIODevice上的所有可用数据。所以下面我假设有一些QByteArray m_rawData,它保存当前未处理的字节,可以是部分电报+可以部分接收的最后一份电报。

2)我会创建一个类似Telegram的类来保存电报数据,粗略地说

class Telegram {
       QString       header;
       int           sequenceNumber;
       unsigned char checkSum;
       QByteArray    data;

       ...

       bool          checkSumOK();  // check is checksum is OK for provided data

}

根据您的口味使用构造函数和运算符(您可以实现复制构造函数/ etc)。 然后,我将使用(&lt;&lt;&lt;&gt;&gt;)运算符扩展此类,以支持QDataStream,该QDataStream在第1部分中提到的临时缓冲区上运行。

因此,一般的概念是您尽快将数据从流读取到临时缓冲区,并在读取完成后从结果缓冲区中获取尽可能多的Telegram实例。然后你使用在QByteArray上应用的QDataSteam你可以安全地使用读取4个字节,读取1个字节等调用而不会产生太大的性能影响,因为一般来说它主要是关于移位指针。

3)当然,如果你谈论极端条件......你可以想到工会(正如前面的答案中提到的那样)在原始数据的直接复制上,但这种方式需要更仔细的编程(特别考虑到x32 / x64拱门以及大/小端子平台)