Мне нужно обработать потоковые двоичные данные (QDataStream) определенной структуры, созданной другой не-Qt программой. Интересно, как лучше интерпретировать эти данные? Допустим, данные структурированы (дано определение структуры) в телеграммах следующим образом и не могут быть изменены мной самостоятельно:
4 байта заголовка | Порядковый номер 2 байта | 1 байтовая контрольная сумма | Данные 10 байтов
Я вижу следующие возможности для обработки данных в классе «Telegram»:
return (array.at(4)<<8) + array.at(5)
для порядкового номера, с не очень элегантно.telegramstruct.squenceNumber
Я вижу потенциальные проблемы с этим методом, такие как endianness и padding.QString strHeader
, При чтении телеграмм из потока данные сохраняются непосредственно в этих переменных. Чтение осуществляется с помощью readRawData или с помощью оператора >> для основных типов. Код должен быть максимально быстрым, так как для обработки требуется много данных. Я использую Qt 5.0.1 на Windows с MinGW.
Мои вопросы:
Большое спасибо за ваши мнения и советы.
Крис
Что ж, извините, у вас не так много времени для написания примеров кода, но я постараюсь дать краткие подсказки.
1) Проблема производительности. Как только у вас есть ограничения производительности, первое, что нужно оптимизировать, — это количество фактических чтений из потока, из которого поступают данные. Что бы это ни было File / Socket / etc, в любом случае это QIODevice. Поэтому первое, что нужно сделать, — это поддерживать некоторый QByteArray, в который вы добавляете все данные, доступные в QIODevice, при каждой попытке / обработке уведомления о получении данных. Поэтому ниже я предполагаю, что есть определенный QByteArray m_rawData, который содержит в настоящее время необработанные байты, которые могут быть некоторым количеством Telegrams + последняя телеграмма, которая может быть получена частично.
2) Я бы сделал класс, такой как Telegram, который содержит данные телеграммы, грубо говоря
class Telegram {
QString header;
int sequenceNumber;
unsigned char checkSum;
QByteArray data;
...
bool checkSumOK(); // check is checksum is OK for provided data
}
с конструкторами и операторами на ваш вкус (вы можете реализовать конструктор копирования / etc) ..
Тогда я бы расширил этот класс с ( <<>> операторы для поддержки QDataStream, который работает с временным буфером, упомянутым в части 1).
Таким образом, общая концепция заключается в том, что вы читаете данные из потока во временный буфер как можно скорее, а после того, как чтение завершено, вы извлекаете из полученного буфера как можно больше экземпляров Telegram. Затем вы работаете с QDataSteam, примененным к QByteArray, вы можете безопасно использовать вызовы чтения 4 байта, чтения 1 байта и т. Д., Не оказывая такого большого влияния на производительность, потому что в основном речь идет о смещении указателей.
3) Конечно, если вы говорите об экстремальных условиях … вы можете подумать о профсоюзах (как упоминалось в предыдущем ответе), чтобы сделать прямое копирование необработанных данных поверх выровненной структуры, но этот способ требует гораздо более тщательного программирования (особенно принимая во внимание рассмотрение арок x32 / x64, а также платформ с прямым и обратным порядком байтов)
Других решений пока нет …