Qt 如何解包包装在QByteArray中的32位整数?

Qt 如何解包包装在QByteArray中的32位整数?,qt,type-conversion,qt5,unpack,qbytearray,Qt,Type Conversion,Qt5,Unpack,Qbytearray,我使用串行通信,在一个QByteArray数组中接收32位整数,用4个单独的字节(小尾端)进行压缩。 我尝试使用QByteArray::toLong()从4个字节中解包值,但转换失败并返回错误的数字: quint8 packed_bytes[] { 0x12, 0x34, 0x56, 0x78 }; QByteArray packed_array { QByteArray(reinterpret_cast<char*>(packed_bytes),

我使用串行通信,在一个
QByteArray
数组中接收32位整数,用4个单独的字节(小尾端)进行压缩。 我尝试使用
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
8个压缩字节[]{0x12、0x34、0x56、0x78};
QByteArray压缩数组{QByteArray(重新解释强制转换(压缩字节),
sizeof(压缩字节))};
bool-isConversionOK;
qint64解包_值{packed_array.toLong(&isConversionOK)};
//在这一点上:
//未打包的_值==0
//isConversionOK==false
预期的
解包\u值为0x78563412(小端解包)。为什么转换失败?

toLong()
将字符*数字
字符串
转换为长字符。不是字节。并且您的值可能不构成字符串“0x78563412”或其十进制等效值。因此结果为0

如果需要对字节值进行长时间解释,可以执行以下操作:

long value;
value == *((long*)packed_bytes.data());
或作为长数组访问字节数组:

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

values[0]; // contains first long
values[1]; // contains second long
...
我不知道我的例子是否是开箱即用的,但它应该说明原理

看看这个例子:

char bytes[] = {255, 0};

QByteArray b(bytes, 2);

QByteArray c("255");

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

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

您可能需要根据endianess更改字节顺序。但它可以满足您的需要。

您可以使用位操纵器构建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);
}
#包括
#包括
#包括
int main()
{
五次8压缩_字节[]{0x12,0x34,0x56,0x78};
QByteArray压缩数组{QByteArray(重新解释强制转换(压缩字节),
sizeof(压缩字节))};
qint64未包装_值=0;
未压缩的_值|=压缩的_数组。位于(0)|

压缩数组。在(1)处,您可以使用
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);
8个压缩字节[]{0x12、0x34、0x56、0x78};
QByteArray压缩_数组{QByteArray(重新解释_转换(压缩_字节)),sizeof(压缩_字节));
QDataStream(压缩_阵列);
setByteOrder(QDataStream::LittleEndian);
int结果;
流>>结果;
qDebug()这里有一个通用的解决方案,可以通过
QDataStream
运行一个
QByteArray
将它转换为“其他类型”(例如问题中特别提出的问题)

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

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

#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 ) }
qint32 toQInt32( const QByteArray &data,
                 const QDataStream::ByteOrder order=QDataStream::BigEndian )
{ byteArrayToType( data, order, qint32 ) }
qint64 toQInt64( const QByteArray &data,
                 const QDataStream::ByteOrder order=QDataStream::BigEndian )
{ byteArrayToType( data, order, qint64 ) }
32位,有符号

qint16 toQInt16( const QByteArray &data,
                 const QDataStream::ByteOrder order=QDataStream::BigEndian )
{ byteArrayToType( data, order, qint16 ) }
qint32 toQInt32( const QByteArray &data,
                 const QDataStream::ByteOrder order=QDataStream::BigEndian )
{ byteArrayToType( data, order, qint32 ) }
qint64 toQInt64( const QByteArray &data,
                 const QDataStream::ByteOrder order=QDataStream::BigEndian )
{ byteArrayToType( data, order, qint64 ) }
64位,有符号

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

谢谢你回答我,但你可以在我的帖子中看到,我将数组转换为
char*
,它将整数转换为字符串,就像你所描述的那样。我遗漏了什么吗?为什么转换失败(如
bool
所示),而不是仅仅返回错误的结果?您能正确打印该字符串并看到写入的正确值吗?那么它应该可以工作。但是如果字节值表示值,而不是其ascii表示,则需要类似我的方法。QByteArray::toLong()将字节解释为\0终止的字符串。嗯,我不确定API为什么使用ASCII,或者为什么它必须\0终止,所以我尝试了您的解决方案,但返回的值不正确:“0x20000078563412”(无论我是将数组解包为小端还是大端,这都是错误的)。它不必以0结尾。但与ascii字符串相关的方法将被视为以0结尾。toLong可以处理字符串。多亏了这个解决方案,但它的级别相当低,只能生成无符号数字,我不确定是否可以使用它来转换例如2字节或3字节的值。当然,像Qt这样庞大的框架已经存在了作为抽象出低级位移位的函数,我必须为此编写测试用例,所以使用Qt中已有的东西肯定会更好。