原文链接:https://blog.csdn.net/qq_34322603/article/details/106457231
QByteArray在串口通讯中经常被使用,通信处理过程中,经常会涉及到数据格式的转换,有一定必要较为全面详细的对QByteArray数据转换与处理部分进行阐述。本文通过以下几个部分加以介绍:
在使用串口发送数据时可以选择字符串发送或者十六进制发送,通常情况下我们习惯选用字符串发送数据。关于两者的区别,需要从计算机存储数据的格式说起。
在计算机中,数据是以二进制的形式存储的,例如十进制 1(10)在计算机中用 0000 0001(2)来表示。在使用字符串方式发送数据的时候,串口软件首先将待数据转换为对应的ASCII码,然后再将这些ASCII码按照二进制的方式一位一位的发送出去;而使用十六进制方式发送数据的时候,串口直接将数据以二进制的方式一位一位的发送出去。
例如我们在串口软件发送框输入 “FF012345”,分别以字符串和十六进制两种方式发送:
串口以字符串发送数据,首先将字符串转化为ASCII码对应的二进制,格式如下
串口发送了8个字节,若在接收端选择字符串接收,则会接收到FF0123456这个字符串;若在接收端选择十六进制接收,则会接收到:
0100 0110 | 0100 0110 | 0011 0000 | 0011 0001 | 0011 0010 | 0011 0011 | 0011 0100 | 0011 0101 这一串数字
串口以十六进制发送数据,首先将发送框中数据转化为如下格式:
串口发送了4个字节,若在接收端选择十六进制接收,则会在接收框显示FF 01 23 45;若在接收端选择字符串接收,则会接收到乱码
仔细对照接收结果就很容易明白字符串发送和十六进制发送的区别了。
从串口读取到的QByteArray数据,一般需要进行提取和解析,此时就需要QByteArray转换为各类型数据。常用转换包括:
1、字符与十六进制转换,例如串口接收到的数据,用字符方式表达,或者将字符串对应的十六进制数据流转化为字符串;
2、转为不同进制数值并显示,如二进制、八进制、十进制和十六进制等;
3、转为整型、浮点型等数值类型;
4、大小写转换;
5、转为字符串类型;
把Hex编码的数据流转换为char存储到QByteArray:
QByteArray text = QByteArray::fromHex("517420697320677265617421");
text.data(); // "Qt is great!"
把QByteArray数据转换为字符串:
QByteArray ba;
ba.resize(3);
ba[0] = 0x30;
ba[1] = 0x31;
ba[2] = 0x32;
qDebug() << ba.toHex(); //return "303132"
尽管QByteArray是一个集合,但也可以作为一个特殊形式的数值用,其灵活的转换格式,可大大方便各种格式数据转换与显示的需求。如显示二进制和十六进制、显示科学计数和指定小数位的数值。示例如下:
把单个字符转为2-36进制数据格式:
int n = 63;
qDebug()<<QByteArray::number(n); // returns "63"
qDebug()<<QByteArray::number(n, 16); // returns "3f"
qDebug()<<QByteArray::number(n, 16).toUpper(); // returns "3F"
qDebug()<<QByteArray::number(n, 2); // returns "111111"
qDebug()<<QByteArray::number(n, 8); // returns "77"
按照指定进制格式直接复制,其中n可以是各类常见数值类型:
int n = 63;
qDebug()<<QByteArray::number(n); // returns "63"
qDebug()<<QByteArray::number(n, 16); // returns "3f"
qDebug()<<QByteArray::number(n, 16).toUpper(); // returns "3F"
qDebug()<<QByteArray::number(n, 2); // returns "111111"
qDebug()<<QByteArray::number(n, 8); // returns "77"
按照指定进制格式直接复制,其中n可以是各类常见数值类型:
QByteArray ba;
int n = 63;
ba.setNum(n); // ba == "63"
ba.setNum(n, 16); // ba == "3f"
把数值按指定格式和小数位转换输出,小数位四舍五入:
QByteArray ba1 = QByteArray::number(12.3456, 'E', 3);
QByteArray ba2 = QByteArray::number(12.3456, 'f', 3);
qDebug()<<ba1; // returns "1.235E+01"
qDebug()<<ba2; // returns "12.346"
QByteArray若为数值,可通过to**方法转为各种类型数据,示例如下:
QByteArray strInt("1234");
bool ok0;
qDebug() << strInt.toInt(); // return 1234
qDebug() << strInt.toInt(&ok0,16); // return 4660, 默认把strInt作为16进制的1234,对应十进制数值为4660
QByteArray string("1234.56");
bool ok1;
qDebug() << string.toInt(); // return 0, 小数均视为0
qDebug() << string.toInt(&ok1,16); // return 0, 小数均视为0
qDebug() << string.toFloat(); // return 1234.56
qDebug() << string.toDouble(); // return 1234.56
QByteArray str("FF");
bool ok2;
qDebug() << str.toInt(&ok2, 16); // return 255, ok2 == true
qDebug() << str.toInt(&ok2, 10); // return 0, ok == false, 转为十进制失败
QByteArray若为带大小写的字符串,可通过toUpper()和toLower()方法实现大小写转换,示例如下:
QByteArray x("Qt by THE QT COMPANY");
QByteArray y = x.toLower();
// y == "qt by the qt company"
QByteArray z = x.toUpper();
// z == "QT BY THE QT COMPANY"
QByteArray与QString互转极为简单,二者从本质上类似,都是连续存储,区别是前者可以存无法显示的字符,后者只存可显示的字符。如QByteArray可以存0x00-0x19,而QString则存储如0x30等可显示字符(0x20-0x7E)。可显示字符可参见ASCII表,链接如下:ASCII可显示字符
QByteArray转为QString示例:
QByteArray ba("abc123");
QString str = ba;
//或str.prepend(ba);
qDebug()<<str ;
//输出:"abc123"
QString转为QByteArray示例:
QString str("abc123");
QByteArray ba = str.toLatin1();
qDebug()<<ba;
//输出:"abc123"
(用于读取textEdit中的字符串数据,并转换为16进制数据,用于串口通信)
例:如果某次传输的数据为0x30 0x38 0x0D 0x32(二进制原始数据),从输入控件textEdit中输入30 38 0D 32,此时从textEdit读取的为字符串"30 38 0D 32",所以要将其转换为二进制0x30 0x38 0x0D 0x32,存入QByteArray中。
QString str1 = ui->lineEdit_SendCmd->text();
QByteArray cmd = QByteArray::fromHex(str1.toLatin1().data()); //按照十六进制编码接入文本
同理:将二进制数据转换为字符串:
ba.resize(3);
ba[0] = 0x30;
ba[1] = 0x31;
ba[2] = 0x32;
qDebug() << ba.toHex(); //return "303132"
//注意收发两端文本要使用对应的编解码
const QByteArray recv_test = socket->readAll();
dataParse(recv_test);
//qDebug()<<"recv msg:"<
QString ret;
QByteArray ba = recv_test.toHex(' ');
qDebug()<<"ba: "<<ba;
//for (int i=0; i
//ret.append(tr("%1 ").arg((quint8)recv_test.at(i),2,16,QLatin1Char('0')).toUpper());
//}
ui->textEdit_message->append(ba.toUpper()); // ret换成ba
//接收串口数据以字符和十六进制数据显示
QByteArray temp = myCom->readAll();
//读取串口缓冲区的所有数据给临时变量temp
ui.textBrowser->insertPlainText(temp);
ui.textEdit_2->insertPlainText(temp.toHex());
//将串口的数据显示在窗口的文本浏览器中