【转】从QDataStream向QByteArray中写入数据时的注意点(QT)

本文详细解析了QDataStream与QByteArray之间的数据读写机制,揭示了为何直接写入可能失败的原因,并提供了修改后的操作符重载实现,确保数据完整读取。同时,文章还介绍了正确写入QByteArray至QDataStream的方法,强调了手动调整QByteArray大小的重要性。

 

最近发现从QDataStream向QByteArray中写入数据常常是写不进去的,通过查看QT的源码:

 

复制代码
QDataStream &operator>>(QDataStream &in, QByteArray &ba)
{
ba.clear();
quint32 len;
in >> len;
if (len == 0xffffffff)
return in;

const quint32 Step = 1024 * 1024;
quint32 allocated = 0;

do {
int blockSize = qMin(Step, len - allocated);
ba.resize(allocated + blockSize);
if (in.readRawData(ba.data() + allocated, blockSize) != blockSize) {
ba.clear();
in.setStatus(QDataStream::ReadPastEnd);
return in;
}
allocated += blockSize;
} while (allocated < len);

return in;
}
复制代码

 

发现原来其中有一句:

 

1
if (in.readRawData(ba.data() + allocated, blockSize) != blockSize) {

它检查读入的数据是不是整数个blockSize,如果不是,那么下面它会将QByteArray清空:

 

1
ba.clear();
 

所以如果想从QDataStream读入数据岛QByteArray中,可以采用下面的方法:

 

复制代码
QDataStream &operator>>(QDataStream &in, QByteArray &ba)
{
ba.clear();
quint32 len;
in >> len;
if (len == 0xffffffff)
return in;

const quint32 Step = 1024 * 1024;
quint32 allocated = 0;

do {
int blockSize = qMin(Step, len - allocated);
ba.resize(allocated + blockSize);
if (in.readRawData(ba.data() + allocated, blockSize) < blockSize) {
return in;
}
allocated += blockSize;
} while (allocated < len);

return in;
}
复制代码

 

 

最后回过头来看一下将QByteArray写入QDataStream的方法

 

复制代码
QDataStream &operator<<(QDataStream &out, const QByteArray &ba)
{
if (ba.isNull() && out.version() >= 6) {
out << (quint32)0xffffffff;
return out;
}
return out.writeBytes(ba, ba.size());
}
复制代码

 

其实是将QByteArray中所有的数据都写入QDatStream中,并没有扩展QByteArray的大小到blockSize,

所以针对这种情况,我们在使用QDataStream向QByteArray中读写数据的时候,需要手动将QByteArray

扩展到blockSize(1024*1024)大小。

转载于:https://www.cnblogs.com/h2zZhou/p/10207409.html

<think> 我们根据引用[1]中提到,在QT处理十六进制与十进制的换,通常涉及QByteArray和QString的换。用户需求是将数字62换为4字节十六进制数据QByteArray。 分析: 1. 用户需要将十进制整数62换为4字节的十六进制表示。 2. 4字节即32位,所以我们需要一个32位整数来存储62,即用quint32(等同于uint32_t)类型。 3. 在QT中,我们可以使用QByteArray来存储原始的字节数据。 4. 换步骤: a. 将整数62换为一个大端序(Big-Endian)或小端序(Little-Endian)的4字节整数。通常网络字节序为大端序,但具体取决于需求。 b. 将换后的字节序列存入QByteArray。 根据引用[1]的提示,我们可以使用QT数据QDataStream来完成,也可以使用内存操作(如memcpy)和字节序换函数。 这里提供两种方法: 方法1:使用QDataStream(会自动处理字节序,默认大端序;也可设置字节序) 方法2:使用位操作和QByteArray的append方法(需要手动处理字节序) 考虑到通用性,我们假设用户需要大端序(网络字节序)的4字节表示。 步骤: 1. 将62换为quint32类型(因为62在0~4294967295范围内,可以无符号表示)。 2. 使用QDataStream将quint32按大端序写入QByteArray。 或者: 1. 通过移位操作分别获取4个字节(从高位到低位)。 2. 将每个字节存入QByteArray注意:62的十六进制表示为0x0000003E(4字节)。 方法1示例代码(使用QDataStream): ```cpp #include <QDataStream> #include <QByteArray> QByteArray intToQByteArrayBigEndian(quint32 value) { QByteArray byteArray; QDataStream stream(&byteArray, QIODevice::WriteOnly); stream.setByteOrder(QDataStream::BigEndian); // 设置为大端序 stream << value; return byteArray; } // 使用:intToQByteArrayBigEndian(62) ``` 方法2:手动换(大端序,高位在前) ```cpp #include <QByteArray> QByteArray intToQByteArrayBigEndian(quint32 value) { QByteArray byteArray; byteArray.append(static_cast<char>((value >> 24) & 0xFF)); // 最高位字节 byteArray.append(static_cast<char>((value >> 16) & 0xFF)); byteArray.append(static_cast<char>((value >> 8) & 0xFF)); byteArray.append(static_cast<char>(value & 0xFF)); // 最低位字节 return byteArray; } ``` 注意:如果用户需要小端序,则只需调整方法1中设置为小端序(QDataStream::LittleEndian),或者在方法2中颠倒字节顺序(从低位到高位)。 方法1(小端序): ```cpp QByteArray intToQByteArrayLittleEndian(quint32 value) { QByteArray byteArray; QDataStream stream(&byteArray, QIODevice::WriteOnly); stream.setByteOrder(QDataStream::LittleEndian); stream << value; return byteArray; } ``` 方法2(小端序): ```cpp QByteArray intToQByteArrayLittleEndian(quint32 value) { QByteArray byteArray; byteArray.append(static_cast<char>(value & 0xFF)); byteArray.append(static_cast<char>((value >> 8) & 0xFF)); byteArray.append(static_cast<char>((value >> 16) & 0xFF)); byteArray.append(static_cast<char>((value >> 24) & 0xFF)); return byteArray; } ``` 用户的问题中要求4字节,所以我们使用32位无符号整数。如果用户没有指定字节序,我们默认提供大端序。 因此,对于数字62,使用大端序得到的QByteArray将包含4个字节:0x00, 0x00, 0x00, 0x3E(十六进制表示)。 验证:我们可以打印出QByteArray的内容,例如使用toHex()方法将其换为可读的十六进制字符串,应该得到"0000003e"(如果大端序的话)。 注意QByteArray存储的是原始字节,所以直接打印可能是不可见字符,我们可以用toHex()换为十六进制字符串查看。 根据用户上次的问题(他们引用了十六进制数组十进制,通常用于串口通信),我们建议明确字节序,因为串口通信中通常有大端序和小端序的约定。 因此,我们给出两个版本的方法,并说明字节序的重要性。 回答: 在QT中,将整数62换为4字节十六进制的QByteArray,可以使用以下两种方法,并注意字节序(大端序或小端序)。 方法1:使用QDataStream(推荐,方便且可设置字节序) ```cpp // 大端序 QByteArray decimalToBigEndianQByteArray(quint32 num) { QByteArray array; QDataStream stream(&array, QIODevice::WriteOnly); stream.setByteOrder(QDataStream::BigEndian); stream << num; return array; } // 小端序 QByteArray decimalToLittleEndianQByteArray(quint32 num) { QByteArray array; QDataStream stream(&array, QIODevice::WriteOnly); stream.setByteOrder(QDataStream::LittleEndian); stream << num; return array; } ``` 方法2:手动移位(直接控制字节) ```cpp // 大端序(高位在前) QByteArray decimalToBigEndianQByteArray(quint32 num) { QByteArray array; array.append((num >> 24) & 0xFF); array.append((num >> 16) & 0xFF); array.append((num >> 8) & 0xFF); array.append(num & 0xFF); return array; } // 小端序(低位在前) QByteArray decimalToLittleEndianQByteArray(quint32 num) { QByteArray array; array.append(num & 0xFF); array.append((num >> 8) & 0xFF); array.append((num >> 16) & 0xFF); array.append((num >> 24) & 0xFF); return array; } ``` 使用示例: ```cpp quint32 number = 62; QByteArray bigEndianArray = decimalToBigEndianQByteArray(number); // 大端序结果:QByteArray包含4个字节:0x00, 0x00, 0x00, 0x3E // 换为十六进制字符串:bigEndianArray.toHex() 得到 "0000003e" QByteArray littleEndianArray = decimalToLittleEndianQByteArray(number); // 小端序结果:QByteArray包含4个字节:0x3E, 0x00, 0x00, 0x00 // 换为十六进制字符串:littleEndianArray.toHex() 得到 "3e000000" ``` 注意:使用手动移位方法,要注意数值的类型(无符号32位整数)以及移位操作的正确性。 根据引用[1]的上下文(串口通信),请根据实际通信协议要求选择大端序或小端序。 如果需要将QByteArray内容以十六进制字符串形式显示(用于调试或显示),可以使用QByteArray::toHex()函数,例如: ```cpp qDebug() << bigEndianArray.toHex(); // 输出 "0000003e" ``` 这样,我们就实现了将62换为4字节十六进制数据QByteArray。 相关问题: 1. 如何在QT中将QByteArray换回整数? 2. 如果数值超过4字节(32位)范围怎么办? 3. 在串口通信中,如何处理多字节数据的字节序问题? </think> ### QT中将数字62换为4字节十六进制QByteArray的方法 在QT中,将十进制整数换为4字节十六进制的QByteArray需要以下步骤: #### 方法1:使用位运算和字节追加(推荐) ```cpp #include <QByteArray> QByteArray convertTo4ByteHex(quint32 number) { QByteArray byteArray; // 按大端序存储(高位在前) byteArray.append(static_cast<char>((number >> 24) & 0xFF)); // 最高位字节 byteArray.append(static_cast<char>((number >> 16) & 0xFF)); byteArray.append(static_cast<char>((number >> 8) & 0xFF)); byteArray.append(static_cast<char>(number & 0xFF)); // 最低位字节 return byteArray; } // 调用示例 QByteArray result = convertTo4ByteHex(62); // 62 → 0x0000003E ``` #### 方法2:使用QDataStream(自动处理字节序) ```cpp #include <QDataStream> #include <QByteArray> QByteArray convertTo4ByteHex(quint32 number) { QByteArray byteArray; QDataStream stream(&byteArray, QIODevice::WriteOnly); stream.setByteOrder(QDataStream::BigEndian); // 设置大端序 stream << number; // 写入4字节整数 return byteArray; } ``` #### 验证换结果 ```cpp // 验证代码 QByteArray data = convertTo4ByteHex(62); qDebug() << "Hex:" << data.toHex(); // 输出: "0000003e" qDebug() << "Size:" << data.size(); // 输出: 4 ``` #### 关键说明: 1. **字节序处理**:默认使用大端序(高位在前),如需小端序: ```cpp // 小端序处理(低位在前) stream.setByteOrder(QDataStream::LittleEndian); // QDataStream方式 // 或手动调整追加顺序:append(LSB), append(...), append(MSB) ``` 2. **数据类型**:使用`quint32`确保4字节长度 3. **结果验证**:`toHex()`将QByteArray为可读十六进制字符串 4. **应用场景**:适用于串口通信、网络协议等需要二进制数据处理的场景[^1] > 两种方法等价,方法1更直接高效,方法2可扩展处理复杂数据结构。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值