如何解压缩QByteArray中包含的32位整数?

时间:2016-04-15 10:58:46

标签: qt type-conversion qt5 unpack qbytearray

我正在使用串行通信,我在QByteArray中收到32位整数,用4个单独的字节(little-endian)打包。 我尝试使用QByteArray::toLong()从4个字节解压缩该值,但它无法转换并返回错误的数字:

quint8 packed_bytes[] { 0x12, 0x34, 0x56, 0x78 };
QByteArray packed_array { QByteArray(reinterpret_cast<char*>(packed_bytes),
                                     sizeof(packed_bytes)) };
bool isConversionOK;
qint64 unpacked_value { packed_array.toLong(&isConversionOK) };
// At this point:
// unpacked_value == 0
// isConversionOK == false

预期的unpacked_value是0x78563412(little-endian解包)。为什么转换失败?

4 个答案:

答案 0 :(得分:3)

toLong() converts a char * digits string to long. Not bytes. And your values likely don't make the up the string "0x78563412" or its decimal equivalent. Hence the 0 result.

If you need the byte values interpreted as long you can do something like:

long value;
value == *((long*)packed_bytes.data());

Or to access an array of bytes as long array:

long * values;
values == (long*)packed_bytes.data();

values[0]; // contains first long
values[1]; // contains second long
...

Don't know whether my examples work out of the box but it should make clear the principle.

Check out this example:

char bytes[] = {255, 0};

QByteArray b(bytes, 2);

QByteArray c("255");

qDebug() << b.toShort() << c.toShort();

qDebug() << *((short*)b.data()) << *((short*)c.data());

the output is:

0 255 
255 13618

You may need to change the byte order depending on the endianess. But it does what you need.

答案 1 :(得分:3)

您可以使用QDataStream来读取二进制数据。

quint8 packed_bytes[] { 0x12, 0x34, 0x56, 0x78 };
QByteArray packed_array { QByteArray(reinterpret_cast<char*>(packed_bytes), sizeof(packed_bytes)) };
QDataStream stream(packed_array);
stream.setByteOrder(QDataStream::LittleEndian);
int result;
stream >> result;
qDebug() << QString::number(result,16);

答案 2 :(得分:1)

您可以使用位操纵器构建qint64:

#include <QtGlobal>
#include <QByteArray>
#include <QDebug>

int main()
{
    quint8 packed_bytes[] { 0x12, 0x34, 0x56, 0x78 };
    QByteArray packed_array { QByteArray(reinterpret_cast<char*>(packed_bytes),
                                         sizeof(packed_bytes)) };

    qint64 unpacked_value = 0;

    unpacked_value |=   packed_array.at(0)       |
                        packed_array.at(1) << 8  |
                        packed_array.at(2) << 16 |
                        packed_array.at(3) << 24;

    qDebug() << QString("0x%1").arg(unpacked_value, 0, 16);
}

答案 3 :(得分:0)

这是一个泛型解决方案,它通过在QByteArray中运行将QDataStream转换为“其他类型”(例如问题中特别要求的内容)(就像接受的答案一样)。

免责声明::我只主张在私有实现中使用它。我知道有很多方法可以滥用 宏!

使用此宏,您可以轻松地产生许多转换函数,例如我提供的示例。如果需要从流中提取各种类型,则以这种方式定义一系列此类功能可能会很有用。显然,您可以针对用例调整宏,关键是 pattern 可以保持基本相同,并放在这样的宏中。

#define byteArrayToType( data, order, type ) \
    QDataStream stream( data ); \
    stream.setByteOrder( order ); \
    type t; \
    stream >> t; \
    return t;

示例函数,仅包装宏:

16位,已签名

qint16 toQInt16( const QByteArray &data,
                 const QDataStream::ByteOrder order=QDataStream::BigEndian )
{ byteArrayToType( data, order, qint16 ) }

32位,已签名

qint32 toQInt32( const QByteArray &data,
                 const QDataStream::ByteOrder order=QDataStream::BigEndian )
{ byteArrayToType( data, order, qint32 ) }

64位,已签名

qint64 toQInt64( const QByteArray &data,
                 const QDataStream::ByteOrder order=QDataStream::BigEndian )
{ byteArrayToType( data, order, qint64 ) }