[英] Best practice: how to interpret/process QDataStream?

查看:126
本文介绍了的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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



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



我看到以下可能性来处理电报类中的数据:


  1. Telegram类有一个私有的QByteArray成员变量。所有数据(17字节)从具有readRawData方法的流中一次读取并存储在那里。用对于序列号的 return(array.at(4)<< 8)+ array.at(5)的公共方法访问和解释变量,不是很优雅。

  2. Telegram类有一个public char [17]成员变量和一个struct。所有数据都从readRawData流读取并存储在那里。当访问变量后,这只是通过结构,如 telegramstruct.squenceNumber 我看到这种方法的潜在问题,如endianness和padding。

  3. Telegram类对每个电报字段都有专用成员变量,例如 QString strHeader 。当从流中读取报文时,数据直接存储在这些变量中。使用readRawData或基本类型的运算符>>进行读取。

代码应尽可能快,因为有大量数据要处理。我在Windows上使用MinGW使用Qt 5.0.1。



我的问题:




    <
  • 正在读取所有的文件,比如读取4个字节,2个字节,1个byte,... like in 3?

  • 使用1和3,我不能使用一个定义的结构提供的头文件,这是不好的做法吗?
  • $ b $ 如何使用解决方案3轻松计算校验和?


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



Chris

解决方案

很好,对不起没有太多时间写代码示例,但会尝试给一个简短的提示。
1)性能问题。一旦你有性能约束,首先要优化的是从数据流来的流的实际读取量。无论是File / Socket / etc它无论如何QIODevice。所以首先要做的是维护某种QByteArray,在每次准备尝试/处理数据收到通知时添加QIODevice上的所有可用数据。所以下面我假设有一些QByteArray m_rawData它保存当前未处理的字节,这可以是一些电报+最后电报可以部分接收。



2)使用类似电报的类来保存电报数据,大致上说

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

...

bool checkSumOK(); //检查所提供数据的校验和是否正确

}


然后我将扩展这个类与(<< >>)运算符,以支持操作在第1部分中提到的临时缓冲区的QDataStream) 。因此,一般的概念是你尽快从流中读取数据到临时缓冲区,在读取完成后,从缓冲区获取尽可能多的Telegram的实例。 。然后你使用QDataSteam应用于QByteArray你可以安全地使用读取4个字节,读取1个字节等调用,而没有那么多的性能影响,因为一般来说,它主要是关于移动指针。



3)当然,如果你谈论极端条件..你可以认为联合(如在上一个答案中提到的)在对齐结构的顶部直接复制原始数据,但是这种方式需要更仔细的编程(特别是考虑x32 / x64拱以及大/小endian平台)


I need to process streamed binary data (QDataStream) of defined structure created by another non-Qt program. I wonder what is the best practice to interpret that data. Let's say the data is structured (struct definition provided) in telegrams as follows and cannot be changed by myself:

4 bytes header | 2 bytes sequence number | 1 byte checksum | 10 bytes data

I see the following possibilities to handle the data in a "Telegram" class:

  1. The Telegram class has a private QByteArray member variable. All data (17 bytes) is read at once from the stream with the readRawData method and stored in there. The variables are accessed and interpreted with public methods like return (array.at(4)<<8) + array.at(5) for the sequence number, with is not very elegant.
  2. The Telegram class has a public char[17] member variable in union with a struct. All data is read from the stream with readRawData and stored in there. When accessing the variables after, this is done only over the struct, like telegramstruct.squenceNumber I see potential problems with this method like endianness and padding.
  3. The Telegram class has private member variables for each of the telegram fields like QString strHeader. When reading the telegrams from the stream, data is stored directly in these variables. Reading is done with readRawData or with the operator>> for basic types.

The code should be as fast as possible since there is a lot of data to process. I am using Qt 5.0.1 on Windows with MinGW.

My questions:

  • Which one of the above solutions is best practice and fast, or is there a better way?
  • Is reading all at once like in 1 faster than reading 4 bytes, 2 bytes, 1 byte, ... like in 3?
  • With 1 and 3, I cannot use a provided header file with a defined struct, would that be bad practice?
  • Is it somehow possible to have kind of a "union" with QByteArray and a structure?
  • How would I easily calculate the checksum with solution 3?

Thanks a lot for your opinions and hints.

Chris

解决方案

Well, sorry dont have that much time to write code examples, but will try to give a brief hints. 1) Performance issue. As soon as you have performance constrains first thing to optimise is an amounts of actual reads from the stream from where data are coming. Whatever it's File/Socket/etc it's anyway QIODevice. So first thing to do is to maintain some kind of QByteArray where you adding all data available on a QIODevice on every ready attempt/handling data received notification. So below I assume there is certain QByteArray m_rawData which holds currently unprocessed bytes, which can be some amount of Telegrams + last telegram which can be received partially.

2) I would make a class like Telegram which holds telegram data, roughly saying

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

       ...

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

}

with constructors and operators on your taste (you can implement copy constructor/etc).. Then I would extend this class with ( <<, >>) operators to support QDataStream which operates on temporary buffer mentioned in part 1).

So general concept is that you read data from the stream to temporary buffer as soon as possible and after read is done you fetch from resulted buffer as many Telegram's instances as possible. Then you work with QDataSteam applied on a QByteArray you can safely use read 4 bytes, read 1 byte etc calls without having that much performance impact because in general it's mostly about shifting pointers.

3) Of course if you talking about extreme condition.. you can think of unions (as being mentioned in previous answer) to make direct copy of raw data on top of a aligned structure but that way requires much more careful programming (especially taking in consideration x32/x64 archs as well as big/little endians platforms)

这篇关于的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆