QByteArray简单入门
来源:互联网 发布:淘宝发布宝贝照片尺寸 编辑:程序博客网 时间:2024/05/22 13:47
Qt通过QByteArray为我们提供了一个字节数组容器。QByteArray既可以用来存储原始的字节,包括'\0',也可以用来存储传统的8-bit 的以'\0'结尾的字符串。使用QByteArray比使用普通的const char* 更方便。并且,在底层,它可以确保其中存储的数据以'\0'结尾,并且通过隐式共享(写时拷贝)策略去减少内存的使用和不必要的数据复制。
当然,除了QByteArray,Qt也提供了QString类去存储字符串。并且,在大多数情况下,我们都选择使用QString。QString 存储的是16位的Unicode字符,所以,在应用程序中使用QString会更容易存储 non-ASCII/non-Latin-1 字符。而且,QString在整个Qt库中也被大量使用到。而Qt库提供QByteArray的用处主要有两个方面:一是用来存储原始的二进制数据,二是在内存比较紧张的情况下,比如嵌入式设备上。
而具体使用QByteArray 的一种通用方式就是直接将const char* 传给它的构造函数。例如,下面的代码构造了一个大小为5的字符数组,其中包含的数据为"hello":
QByteArray ba("Hello");
虽然,对这个对象调用size() 成员函数会返回5,但QByteArray 仍然包含了一个'\0'在字符串最后,以此来确保如果一个函数需要一个指向该对象底层数据的指针时,该指针所指的数据以'\0'结束。另外,当你使用这种方式来创建QByteArray对象时,QByteArray 会采取深拷贝的动作,所以,在你创建完QByteArray的对象后,你还可以修改作为参数的字符串而不会对程序产生任何副作用。当然,如果你处于性能考虑,不想采用深拷贝的方式,那么你可以使用QByteArray的静态方法fromRawData()来创建QByteArray对象。
另一种创建QByteArray对象的方式是先使用resize() 函数设置对象的大小,即要存储的字节数,然后一个字节一个字节的初始化。因为QByteArray和c++数组一样,使用基于0的索引,并且提供了[]运算符,所以这种方式也是非常的方便的。例如:
QByteArray ba; ba.resize(5); ba[0] = 0x3c; ba[1] = 0xb8; ba[2] = 0x64; ba[3] = 0x18; ba[4] = 0xca;
而对于访问其中的每一个字节,除了使用上面的[]运算符外,我们还可以使用它的at() 成员函数。并且,at() 通常都比[]运算符更快,因为它从不会发生深拷贝。比如,下面的代码:
for (int i = 0; i < ba.size(); ++i) { if (ba.at(i) >= 'a' && ba.at(i) <= 'f') cout << "Found character in range [a-f]" << endl; }
而如果想一次提取多个字节的话,可使用left()、right()、mid()成员函数。
我们刚才说过,QByteArray通常用来存储原始的二进制数据。所以,可以在QByteArray中存储'\0'。而成员函数size() 还是可以返回整个数组的大小,包括中间的'\0',但不包括由QByteArray自动添加到最后的'\0'。例如:
QByteArray ba1("ca\0r\0t"); ba1.size(); // Returns 2. ba1.constData(); // Returns "ca" with terminating \0. QByteArray ba2("ca\0r\0t", 3); ba2.size(); // Returns 3. ba2.constData(); // Returns "ca\0" with terminating \0. QByteArray ba3("ca\0r\0t", 4); ba3.size(); // Returns 4. ba3.constData(); // Returns "ca\0r" with terminating \0. const char cart[] = {'c', 'a', '\0', 'r', '\0', 't'}; QByteArray ba4(QByteArray::fromRawData(cart, 6)); ba4.size(); // Returns 6. ba4.constData(); // Returns "ca\0r\0t" without terminating \0.
并且,我们可以使用qstrlen() 函数来得到第一个'\0'之前的字符串的长度。还有,上面讲QByteArray对象的创建时,我们提到了resize() 函数,但注意,当调用该函数后,那些新分配的字节是未定义的,为了给这些字节设置特定的值,可以使用fill() 函数。
除了使用operator[] 和 at() 函数进行访问外,我们还可以使用data() 和 constData() 直接得到数组底层的数据的指针。这个返回的指针会一直保持有效,直到下次non-const函数被调用;同时,也可以确保这些数据是以'\0'结尾的,除非该QByteArray对象是有raw data 创建的。返回的字符串中也会自动保护QByteArray添加在最后的'\0'。
对于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() 函数的前两个参数,是指开始删除的位置和要删除的字符的个数。
当向一个非空的数组追加数据时,数组会重新分配空间然后将数据拷贝进去。如果考虑的性能问题,也可以事先调用一次reserve() 函数,为数组预分配一部分空间,这样可以省去每次追加数据都再分配的开销。可以使用capacity() 函数取得QByteArray当前实际分配了多少内存。
向一个空的数组追加数据不会发生拷贝。
在我们实际开发使用中,经常会需要从字节数组的两端去掉空白字符,如'\n'、'\t'、' ' 等,此时,可以使用trimmed() 函数;如果你在去掉两端空白字符的同时,还想把中间连续的多个空白字符替换成一个,可以使用simplified() 函数。
同样,QByteArray的查找也是提供了indexOf() 和 lastIndexOf() 。顾名思义,一个从前往后查找,一个从后往前查找。如果查找成功,都返回字符或子串的下标位置,否则返回-1。如果只是想检测是否包含某个字符或子串,可以简单的使用contains() 函数;如果想知道一个特定的字符或子串在字节数组里出现了几次,可以使用count() 函数。替换某个字符或子串也是类似的,可以使用replace() 函数。
最后需要说明的是,由于历史原因,QByteArray区分字节数组为null和字节数组为空。null表示一个字节数组是使用QByteArray的默认构造函数创建的;而一个空的字节数组是大小为0 的字节数组。它们的关系是,一个null字节数组一定是个空数组,但是反过来不成立。切记!
QByteArray().isNull(); // returns true QByteArray().isEmpty(); // returns true QByteArray("").isNull(); // returns false QByteArray("").isEmpty(); // returns true QByteArray("abc").isNull(); // returns false QByteArray("abc").isEmpty(); // returns false
上面说了这么多关于QByteArray的信息和用法,接下来,我们在一并简单说下和QByteArray相关的另外两个类,一个是QByteArrayList,一个是QByteArrayMatcher。
QByteArrayList顾名思义就是QByteArray的链表,类似于QList<QByteArray>。所以,所有QList的函数都可以应用到QByteArrayList。例如,你可以使用isEmpty() 来测试链表是否为空,使用append()、prepend()、insert()、replace()、等待函数去修改一个QByteArrayList。除了这些QList的函数外,QByteArrayList额外提供了几个join() 函数,可以将QByteArrayList中的元素连接成一个单独的QByteArray。
还有,Qt库提供QByteArrayList的目的和QStringList是完全不同的。比如,QStringList有很多成员函数可以用来操作其中的元素,而QByteArrayList没有。通常情况下,当我们想表示可打印类字符串的列表时,优先选用QStringList。QByteArrayList通常用来处理高效的连接大量二进制数据,比如,从一个顺序的io设备中接收数据时。
QByteArrayMatcher类用来在QByteArray中高效的反复查找一个字节序列。在反复查找的情况下,通过使用该类的对象和其成员函数indexIn() 比直接用QByteArray的indexOf() 进行查找更高效。但是,该类对于单字节的查找情况没有更高的效率。其使用方法是,使用要查找的QByteArray序列创建一个QByteArrayMatcher的对象,然后通过indexIn()成员函数在目标字节数组中进行查找。indeIn() 的具体声明如下:
int QByteArrayMatcher::indexIn(const QByteArray &ba, int from = 0) constint QByteArrayMatcher::indexIn(const char *str, int len, int from = 0) const
如果查找成功,返回子字节数组在目标数组的下标位置;如果查找失败,返回-1。
若在构造QByteArrayMatcher的对象时,没有为其传入要查找的pattern,也可以在以后通过setPattern() 来设置。
QByteArray QByteArrayMatcher::pattern() constvoid QByteArrayMatcher::setPattern(const QByteArray &pattern)
对于这上类,我们建立一个控制台程序,来为大家简单的演示一下:
新建项目的步骤就略过了,启动Qt Creator,点击文件->新建文件或项目->选择 Qt Console Application 即可。
下面,给出测试代码:
#include <QCoreApplication>#include <QByteArray>#include <QByteArrayMatcher>#include <QByteArrayList>#include <QDebug>int main(int argc, char *argv[]){ QCoreApplication a(argc, argv); QByteArray array("Hello "); array.append("world "); array.prepend("you "); qDebug() << "Origin byte array: " << array; QByteArrayMatcher matcher("world"); int pos = matcher.indexIn(array); if(pos == -1) { qDebug() << "Search failed"; } else { qDebug() << "The position is " << pos; } QByteArrayList byteList; byteList << "I" << "like" << "Qt"; qDebug() << "byteList: " << byteList; QByteArray joinArray = byteList.join("-"); qDebug() << "joinArray: " << joinArray; return a.exec();}
- QByteArray简单入门
- Qt入门-QByteArray类
- QByteArray
- QByteArray
- QString QbyteArray
- QByteArray类
- QT:QByteArray和QByteArray、char *
- 简单入门
- Qt5 QByteArray to QString & QString to QByteArray
- QByteArray显示中文
- QString Char* QByteArray转换
- QString Char* QByteArray转换
- QByteArray和 QVariant--51
- QByteArray和QVariant
- QByteArray和QVariant(ZZ)
- QByteArray转向QString
- 关于字节数组QByteArray
- QImage - QByteArray - QString
- 例题(例1.4-1、例1.4-2)及课堂解答题(6道)
- openGL正交矩阵转屏幕矩阵
- C#之if条件语句
- Eclipse中properties文件中文乱码问题
- 深入浅出ES6(六):解构 Destructuring
- QByteArray简单入门
- mysql联表查询
- 自定义android RadioButton样式
- 已签名apk文件获取签名文件的MD5,签名信息
- 多线程学习(五)之Callable&Future
- opencv 简单的makefile
- Libevent源码分析-----配置event_base
- fstream 一点总结
- 【C#/WPF】用Thumb做可拖拽的UI控件