前言
Qt中无论是串口serialport还是tcp网络通信等,直接接收到(或者要发送)的数据都是QByteArray,之后的数据处理部分,无论你转为char*/char[]还是使用最多的QString,都得通过QByteArray转换而来,那我们在后面的数据处理部分可不可以直接用QByteArray呢?这就要求我们对QByteArray有很深刻的认识。
一. QByteArray 类
1. 初始化
QByteArray ba(48, 0); //创建一个长度为48字节,初始值为0的字节数组
2. 访问和赋值
访问QByteArray主要有4中方式,分别为[]、at()、data[]和constData[]。其中[]和data[]为可读可写,at()和constData[]仅为可读。如果仅是读,则通过at()和constData[]访问速度最快,因可避免复制处理。示例如下:
QByteArray ba;
ba.resize(6);
ba[0] = 0x3c;
ba[1] = 0xb8;
ba[2] = 0x64;
ba[3] = 0x18;
ba[4] = 0xca;
ba.data()[5] = 0x31;
qDebug()<<"[]"<<ba[2]; //[] d
qDebug()<<"at()"<<ba.at(2); //at() d
qDebug()<<"data()"<<ba.data()[2]; //data() d
qDebug()<<"constData()"<<ba.constData()[2]; //constData() d
qDebug()<<"constData()"<<ba.constData()[5]; //constData() 1
at()可以比operator []()更快,因为它不会导致深层拷贝发生。
要一次提取多个字节,请使用 left(),right() 或mid()。
QByteArray可以嵌入“\0” 字节,size()函数总是返回整个数组的大小,包括嵌入的’\ 0’字节,但不包括QByteArray添加的终止’\ 0’.调用resize()后,新分配的字节具有未定义的值。 要将所有字节设置为特定值,请调用fill()。要获取指向实际字符数据的指针,请调用data()或constData()。这些函数返回一个指向数据开头的指针。 指针保持有效,直到在QByteArray上调用了非const函数。除了从原始数据创建QByteArray之外,还保证数据以”\ 0”字节结尾。这个’\ 0’字节由QByteArray自动提供,并不会在size()中计算。
3. 添加、删除、插入和替换
QByteArray类提供以下用于修改字节数据的基本功能:append(),prepend() ,insert(),replace()和remove()。
QByteArray x("and");
x.prepend("rock "); // x == "rock and" 前置
x.append(" roll"); // x == "rock and roll" 附加
x.replace(5, 3, "&"); // x == "rock & roll" 替代
这个 replace() 和remove()函数,前两个参数是从其开始擦除的位置和应该被擦除的字节数。
一个常见的要求是从字节数组(’\ n’,’\ t’,’等)中删除空白字符,如果要从QByteArray两端删除空格,请使用trimmed()。 如果要从两端移除空格并用字符数组中的单个空格替换多个连续的空格,请使用simplified()。
4.查找和比较
如果要查找QByteArray中特定字符或子字符串的所有出现,请使用indexOf()或lastIndexOf()。 indexOf()从给定的索引位置开始搜索,lastIndexOf()向后搜索。两者返回字符或子字符串的索引位置, 如果它们找到它; 否则返回-1 。例如,这是一个典型的循环,它查找特定子字符串的所有出现:
QByteArray ba("We must be <b>bold</b>, very <b>bold</b>");
int j = 0;
while ((j = ba.indexOf("<b>", j)) != -1)
{
cout << "Found <b> tag at index position " << j << endl;
++j;
}
5. QByteArray转换和处理
从串口读取到的QByteArray数据,一般需要进行提取和解析,此时就需要QByteArray转换为各类型数据。常用转换包括:
1)转为HEX,用于显示十六进制,这点在调试时特别有用,因为大多HEX码是没有字符显示的,如0x00、0x20等等;
2)转为不同进制数值并显示,如二进制、八进制、十进制和十六进制等;
3)转为整型、浮点型等数值类型;
4)大小写转换;
5)转为字符串类型;
5.1 HEX转换
把Hex编码转换为char存储到QByteArray:
QByteArray text = QByteArray::fromHex("517420697320677265617421");
text.data(); // returns "Qt is great!"
把QByteArray转为Hex编码:
QByteArray ba;
ba.resize(3);
ba[0] = 0x30;
ba[1] = 0x31;
ba[2] = 0x32;
qDebug() << ba.toHex(); //return "303132"
5.2 转为不同数据格式
尽管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可以是各类常见数值类型:
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"
5.3 字符串数值转为各类数值
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, 转为十进制失败
5.4 大小写转换
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"
5.5 与字符串相互转换
QByteArray与QString互转极为简单,二者从本质上类似,都是连续存储,区别是前者可以存无法显示的字符,后者只存可显示的字符。如QByteArray可以存0x00-0x19,而QString则存储如0x30等可显示字符(0x20-0x7E)。可显示字符可参见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"
如果您只想检查QByteArray是否包含特定字符或子字符串,请使用contains()。
如果要查找字节数组中特定字符或子字符串的次数,请使用count()。
如果要将特定值的所有出现替换为另一个,请使用两个参数replace()重载之一。
可以使用运算符<(),运算符<=(),运算符==(),运算符>=()等重载运算符来比较QByteArray。比较完全基于字符的数值,非常快,但不是我们期望的。QString :: localeAwareCompare()是排序用户界面字符串的更好选择。
由于历史原因,QByteArray区分了一个Null byte 和 empty byte. 我们建议您始终使用isEmpty()。
QByteArray().isNull(); //true
QByteArray().isEmpty(); //true
QByteArray("").isNull(); //false
QByteArray("").isEmpty(); //true
qDebug() << QByteArray((const char *)0).isNull(); //true
qDebug() << QByteArray((const char *)0).isEmpty(); //true
if((const char *)0 == NULL) //true
qDebug() << "true.";
二. QByteArray 的成员函数
参考: