在QT中,如何从QByteArray中解析出部分数据

qq_38154303 2017-04-15 04:35:33
各位大侠,最近写一个客户端的程序,把接收到服务器的报文存在QByteArray中,报文的格式是
28 个字节的header + 1个字节的 data + 4个字节的Crc,其中header中包含有数据长度等等信息,现在想根据报文的格式把
QByteArray中的数据解析出来,只要data部分的数据就可以。

struct M300Pro //报文结构
{
struct header COMA; //28个字节
UCHAR Data; //1个字节
UINT Crc; // 4个字节
};

void readMessage(void)
{
QByteArray recvmesg = sock->readAll();
}

怎么从QByteArray中解析出data中内容,小弟入行QT不久,还请各位指教,提供个思路。
...全文
12100 14 打赏 收藏 转发到动态 举报
写回复
用AI写文章
14 条回复
切换为时间正序
请发表友善的回复…
发表回复
北漂的牛犊 2019-06-18
  • 打赏
  • 举报
回复
引用 13 楼 qq_24818721 的回复:
[quote=引用 12 楼 北漂的牛犊 的回复:]
我的是这么写的,效果没问题
QByteArray ba;
signed short Angle[3] = {0};
char *data = NULL;
//QString str;
while(udpsocket->hasPendingDatagrams())
{
ba.resize(udpsocket->pendingDatagramSize());
udpsocket->readDatagram(ba.data(),ba.size());
//ui->textEdit_recv->setText(ba.data());

data = ba.data();
Angle[0] = char2hex(data[10])<<12 | char2hex(data[11])<<8 | char2hex(data[12])<<4 | char2hex(data[13]);
Angle[1] = char2hex(data[14])<<12 | char2hex(data[15])<<8 | char2hex(data[16])<<4 | char2hex(data[17]);
//Angle[2] = char2hex(data[18])<<12 | char2hex(data[19])<<8 | char2hex(data[20])<<4 | char2hex(data[21]);

OffsetYaw = Angle[0]/100;
OffsetPitch = -Angle[1]/100;
// str = QString::number(Angle[0]/100,10); str += "\r\n";
// str += QString::number(Angle[1]/100,10); str += "\r\n";
// str += QString::number(Angle[2]/100,10); str += "\r\n";

}


问下您那个char2hex函数是怎么写的?[/quote]自己封装
qq_24818721 2019-06-12
  • 打赏
  • 举报
回复
引用 12 楼 北漂的牛犊 的回复:
我的是这么写的,效果没问题
QByteArray ba;
signed short Angle[3] = {0};
char *data = NULL;
//QString str;
while(udpsocket->hasPendingDatagrams())
{
ba.resize(udpsocket->pendingDatagramSize());
udpsocket->readDatagram(ba.data(),ba.size());
//ui->textEdit_recv->setText(ba.data());

data = ba.data();
Angle[0] = char2hex(data[10])<<12 | char2hex(data[11])<<8 | char2hex(data[12])<<4 | char2hex(data[13]);
Angle[1] = char2hex(data[14])<<12 | char2hex(data[15])<<8 | char2hex(data[16])<<4 | char2hex(data[17]);
//Angle[2] = char2hex(data[18])<<12 | char2hex(data[19])<<8 | char2hex(data[20])<<4 | char2hex(data[21]);

OffsetYaw = Angle[0]/100;
OffsetPitch = -Angle[1]/100;
// str = QString::number(Angle[0]/100,10); str += "\r\n";
// str += QString::number(Angle[1]/100,10); str += "\r\n";
// str += QString::number(Angle[2]/100,10); str += "\r\n";

}


问下您那个char2hex函数是怎么写的?
北漂的牛犊 2019-01-22
  • 打赏
  • 举报
回复
我的是这么写的,效果没问题
QByteArray ba;
signed short Angle[3] = {0};
char *data = NULL;
//QString str;
while(udpsocket->hasPendingDatagrams())
{
ba.resize(udpsocket->pendingDatagramSize());
udpsocket->readDatagram(ba.data(),ba.size());
//ui->textEdit_recv->setText(ba.data());

data = ba.data();
Angle[0] = char2hex(data[10])<<12 | char2hex(data[11])<<8 | char2hex(data[12])<<4 | char2hex(data[13]);
Angle[1] = char2hex(data[14])<<12 | char2hex(data[15])<<8 | char2hex(data[16])<<4 | char2hex(data[17]);
//Angle[2] = char2hex(data[18])<<12 | char2hex(data[19])<<8 | char2hex(data[20])<<4 | char2hex(data[21]);

OffsetYaw = Angle[0]/100;
OffsetPitch = -Angle[1]/100;
// str = QString::number(Angle[0]/100,10); str += "\r\n";
// str += QString::number(Angle[1]/100,10); str += "\r\n";
// str += QString::number(Angle[2]/100,10); str += "\r\n";

}
sy123sq 2018-12-12
  • 打赏
  • 举报
回复
楼主,我想问一下udp中报文存在字节数组中怎么解析?
QtGreenHand 2018-03-09
  • 打赏
  • 举报
回复
我的问题跟你的这个问题差不多,也是想从QByteArray中读取一定结构的数据,现在已经把数取到了QByteArray中了,但是不知道怎么按照我需要的结构读取出来。
QtGreenHand 2018-03-09
  • 打赏
  • 举报
回复
怎么解决的?
qq_38154303 2017-04-18
  • 打赏
  • 举报
回复
引用 6 楼 qq_38154303 的回复:
[quote=引用 5 楼 ipqtjmqj 的回复:] [quote=引用 4 楼 qq_38154303 的回复:] [quote=引用 1 楼 ipqtjmqj 的回复:] 看QByteArray的文档 它和std::string一下,有下标运算符,所以直接recvmesg[28]就可以获取到数据
谢谢各位大侠的回复,楼上两种方法都是可以的,已经实现了报文data部分的获取,发现data不止一个字节,data的内容包含很多的字符串,每个字符串之间用接收符隔开,根据接收符把data中的每个字符串拆拆出来,请教一下各位这个接收符是什么鬼!(每个字符串之间的接收符的顺序一定)。[/quote] 你需要类似于js中spilit的方法. c++中可以用getline,getline第三个参数默认为换行符,也可以自定义[/quote] 谢谢大神秒回!能不能用自定义的方法给我举个例子,小弟刚学,基础不是很好!有劳了。 假设data中内容为S49568211564 /接收符/ aacd /接收符/ 7_dasf /接收符/[/quote]
问题已解决,谢谢大神!
自信男孩 2017-04-17
  • 打赏
  • 举报
回复
QByteArray这个是什么类型, 如果是报文缓存到一个char类型的数组里,直接用数组偏移即可。比如
data = *(buf+28);
qq_38154303 2017-04-17
  • 打赏
  • 举报
回复
引用 5 楼 ipqtjmqj 的回复:
[quote=引用 4 楼 qq_38154303 的回复:] [quote=引用 1 楼 ipqtjmqj 的回复:] 看QByteArray的文档 它和std::string一下,有下标运算符,所以直接recvmesg[28]就可以获取到数据
谢谢各位大侠的回复,楼上两种方法都是可以的,已经实现了报文data部分的获取,发现data不止一个字节,data的内容包含很多的字符串,每个字符串之间用接收符隔开,根据接收符把data中的每个字符串拆拆出来,请教一下各位这个接收符是什么鬼!(每个字符串之间的接收符的顺序一定)。[/quote] 你需要类似于js中spilit的方法. c++中可以用getline,getline第三个参数默认为换行符,也可以自定义[/quote] 谢谢大神秒回!能不能用自定义的方法给我举个例子,小弟刚学,基础不是很好!有劳了。 假设data中内容为S49568211564 /接收符/ aacd /接收符/ 7_dasf /接收符/
ipqtjmqj 2017-04-17
  • 打赏
  • 举报
回复
引用 4 楼 qq_38154303 的回复:
[quote=引用 1 楼 ipqtjmqj 的回复:] 看QByteArray的文档 它和std::string一下,有下标运算符,所以直接recvmesg[28]就可以获取到数据
谢谢各位大侠的回复,楼上两种方法都是可以的,已经实现了报文data部分的获取,发现data不止一个字节,data的内容包含很多的字符串,每个字符串之间用接收符隔开,根据接收符把data中的每个字符串拆拆出来,请教一下各位这个接收符是什么鬼!(每个字符串之间的接收符的顺序一定)。[/quote] 你需要类似于js中spilit的方法. c++中可以用getline,getline第三个参数默认为换行符,也可以自定义
qq_38154303 2017-04-17
  • 打赏
  • 举报
回复
引用 1 楼 ipqtjmqj 的回复:
QByteArray的文档 它和std::string一下,有下标运算符,所以直接recvmesg[28]就可以获取到数据
谢谢各位大侠的回复,楼上两种方法都是可以的,已经实现了报文data部分的获取,发现data不止一个字节,data的内容包含很多的字符串,每个字符串之间用接收符隔开,根据接收符把data中的每个字符串拆拆出来,请教一下各位这个接收符是什么鬼!(每个字符串之间的接收符的顺序一定)。
qq_38154303 2017-04-17
  • 打赏
  • 举报
回复
谢谢各位大侠的回复,楼上两种方法都是可以的,已经实现了报文data部分的获取,发现data不止一个字节,data的内容包含很多的字符串,每个字符串之间用接收符隔开,根据接收符把data中的每个字符串拆拆出来,请教一下各位这个接收符是什么鬼!(每个字符串之间的接收符的顺序一定)。
ipqtjmqj 2017-04-16
  • 打赏
  • 举报
回复
QByteArray的文档 它和std::string一下,有下标运算符,所以直接recvmesg[28]就可以获取到数据
void Widget::Select() //查询 { QString name = ui->lineEdit->text(); model->setFilter(QObject::tr("id = '%1'").arg(name)); //根据姓名进行筛选 model->select(); //显示结果 } void Widget::Delect() //删除当前行 { int curRow = ui->tableView->currentIndex().row(); //获取选的行 model->removeRow(curRow); //删除该行 int ok = QMessageBox::warning(this,tr("删除当前行!"),tr("你确定" "删除当前行吗?"), QMessageBox::Yes,QMessageBox::No); if(ok == QMessageBox::No) { model->revertAll(); //如果不删除,则撤销 } else model->submitAll(); //否则提交,在数据删除该行 } void Widget::Add() //插入记录 { int rowNum = model->rowCount(); //获得表的行数 int id = 10; model->insertRow(rowNum); //添加一行 model->setData(model->index(rowNum,0),id); //model->submitAll(); //可以直接提交 } void Widget::Back() //返回全表 { model->setTable("student"); //重新关联表 model->setHeaderData(0, Qt::Horizontal, "Time"); model->setHeaderData(1, Qt::Horizontal, "Temperature"); model->select(); //这样才能再次显示整个表的内容 } void Widget::Amend() //提交修改 { model->database().transaction(); //开始事务操作 if (model->submitAll()) { model->database().commit(); //提交 } else { model->database().rollback(); //回滚 QMessageBox::warning(this, tr("tableModel"), tr("数据库错误: %1").arg(model->lastError().text())); } } void Widget::Get_time() { QString string; QTime current_time = QTime::currentTime(); int hour = current_time.hour(); int minute = current_time.minute(); int second = current_time.second(); // int msec = current_time.msec(); string=QString("%1").arg(hour)+":"+QString("%1").arg(minute) +":"+QString("%1").arg(second); ui->Receive->append(string); //qDebug() insertRow(rowNum); //添加一行 model->setData(model->index(rowNum,0),string); model->submitAll(); } void Widget::readMyCom() { QByteArray temp = myCom->readAll(); if(temp.size()!=0) { QString string; QTime current_time = QTime::currentTime(); int hour = current_time.hour(); int minute = current_time.minute(); int second = current_time.second(); // int msec = current_time.msec(); string=QString("%1").arg(hour)+":"+QString("%1").arg(minute) +":"+QString("%1").arg(second); ui->Receive->append(string); //qDebug() insertRow(rowNum); //添加一行 model->setData(model->index(rowNum,0),string); model->setData(model->index(rowNum,1),temp); model->submitAll(); data_light=temp.toInt(); } ui->Receive->append(temp); } void Widget::openCom() { QString portName = ui->portNameComboBox->currentText(); myCom = new Win_QextSerialPort(portName,QextSerialBase::EventDriven); myCom ->open(QIODevice::ReadWrite); if(ui->baudRateComboBox->currentText()==tr("9600")) myCom->setBaudRate(BAUD9600); else if(ui->baudRateComboBox->currentText()==tr("115200")) myCom->setBaudRate(BAUD115200); myCom->setFlowControl(FLOW_OFF); myCom->setTimeout(500); connect(myCom,SIGNAL(readyRead()),this,SLOT(readMyCom())); ui->openMyComBtn->setEnabled(false); ui->closeMyComBtn->setEnabled(true); ui->baudRateComboBox->setEnabled(false); ui->portNameComboBox->setEnabled(false); }

4,356

社区成员

发帖
与我相关
我的任务
社区描述
通信技术相关讨论
社区管理员
  • 网络通信
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧