QDataStream处理数组或字符串

QDataStream提供的读写二进制数据的能力很强,使用也很方便,非常适合将自定义的数据类型进行序列化。但是在使用的过程中也有一些问题需要注意。


QDataStream处理char数组

考虑一下通过QDataStream将char数组输入到QByteArray中,一般网络报文序列化可能会遇到。

1. 问题的产生
char fileName[100];
memset(fileName,0,100);
QByteArray packData;
packData.clear();
QDataStream in(&packData,QIODevice::ReadWrite);

in.setByteOrder(QDataStream::BigEndian);
in.setVersion(QDataStream::Qt_5_10);

in<<fileName;
qDebug()<<"print : "<<packData.length();

以上代码的输出结果是print : 5;

通过<<输入时,会先放4个字节,作为长度;因为fileName初始化为0,QDataStream取第一个字节时,就遇到了0,它认为已经结束了,所以长度是5。

memset(fileName,1,100);
...
in<<fileName;
qDebug()<<"print : "<<packData.length();

要是fileName没有结束符,其实总长度应该是4+100,但是结果却是106。也是不正确的。

2. 使用QDataStream::writeRawData方法

不能用操作符,就直接调方法。

in.writeRawData(fileName,100);
qDebug()<<"print : "<<packData.length();

以上代码的输出刚好是100,它没有在前面补4字节的长度;读的时候应该用QDataStream::readRawData

3. 使用QDataStream::writeBytes方法
in.writeBytes(fileName,100);
qDebug()<<"print : "<<packData.length();

以上代码的输出是104,说明它在前面补了4字节的长度;

读的时候应该用QDataStream::readBytes(char *&s, uint &l)

但注意形参s是指针的引用,在方法内部会分配内存,所以在外部我们不需要分配内存,但要及时使用delete[]释放。


如果QDataStream是ReadWrite模式的

QDataStream既可用于读入又可用于读出,那么存在一种情况,把字符串读入到ByteArray中,然后又立即输出到另一个空字符串中。

QByteArray tmpBytes;
QDataStream dataRWStream(&tmpBytes,QIODevice::ReadWrite);
dataRWStream.setByteOrder(QDataStream::BigEndian);
dataRWStream.setVersion(QDataStream::Qt_5_10);

char dataArrayOne[10];
memset(dataArrayOne,0,10);
QString strData("this");
memcpy(dataArrayOne,strData.toStdString().c_str(),strData.length());

dataRWStream.writeRawData(dataArrayOne,10);

char dataArrayTwo[10];
memset(dataArrayTwo,0,10);
// 先注释这一句
//dataRWStream.device()->seek(0);
dataRWStream.readRawData(dataArrayTwo,10);
qDebug()<<"test :"<<dataArrayTwo;

上例的执行结果输出为空的;也就是说dataArrayTwo中没有数据。取消注释dataRWStream.device()->seek(0);这一句,输出“this”,达到目的。

为什么呢,本例中QDataStream构造函数的参数,QByteArray不是继承自QIODevice,QDataStream在处理时会创建一个QBuffer,QBuffer是继承自QIODevice的,QIODevice都有一个文件指针,指向当前位置,读入字符串后,指针指向第11个地址,输出时仍然从第11个地址开始,当然没有数据了,此时应当回调到第0个地址上,才能读取到数据;

而 dataRWStream.device()->seek(0);

就是用于重置指针位置的。


QDataStream读入QString需要注意的

QString在QT中以Unicode编码,一个字符占两个字节。

QByteArray tmpBytes;
QDataStream dataRWStream(&tmpBytes,QIODevice::ReadWrite);
dataRWStream.setByteOrder(QDataStream::BigEndian);
dataRWStream.setVersion(QDataStream::Qt_5_10);


QString strData("123456789");
dataRWStream<<strData;

qDebug()<<"test :"<<tmpBytes.length();

将strData通过QDataStream输入tmpBytes,tmpBytes的长度本应该是9+4(填入4字节保存长度)=13的;但执行结果却是22。因为QString的编码规则,所以应当是字符个数9*2+4(填入4字节保存长度)=22。

  • 8
    点赞
  • 38
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值