Qt学习(14)

Qt学习(14)——使用QByteArray

本节学习 QByteArray 的两种用法,第一种作为字符串处理类,类似 QString ,但 QByteArray内部字符编码不确定,所以要慎用。第二种是作为纯的字节数组,里面可以包含多个 ‘\0‘ ,经常用于网络数据的接收和发送。

1 QByteArray和char

Qt最常用的字符串类是内码固定的QString,而针对传统类似C语言char*的字符串,Qt提供了QByteArray类来处理。QString的字符单元是QChar,QByteArray的字节单元是char。头文件<QByteArray>不仅自身以类的形式提供,它还针对传统C语言的字符串函数做了安全版本的封装,都加了q字母前缀,如qstrlen、qstrncmp、qstrcpy,这些是全局函数,专门处理传统C语言的char*字符串,用法与C语言风格完全类似,比较简单。

QByteArray类可以处理以‘\0’结尾的传统字符串,包括UTF-8编码和其他如GBK、Big5等多字节编码的字符串,在作为字符串使用时,QByteArray内部字符编码格式是不限定的,可以是任意的编码,所以程序员自己必须要事先确定程序会用到哪种编码的QByteArray。因为Qt5源文件规定是UTF-8编码,所以QByteArray内部使用UTF-8编码的字符串居多。QByteArray在赋值、传参数、返回值时也是使用隐式共享机制提高运行效率,只有字符串发生修改时才会执行深拷贝。

在文件处理、网络数据收发等场景,QByteArray类是作为纯字节数组来使用的,里面可以包含任意数据,比如一堆‘\0’,这是不要拿他当字符串看,它的存储长度与qstrlen计算的长度经常不一致。对于网络数据收发,QByteArray经常配合QDateStream使用,对Qt数据类型做串行化(Serializing)。

2、QByteArray作为字符串使用

QByteArray类作为字符串使用时,它会自动在字符串末尾添加‘ \0 ‘ ,末尾的‘ \0 ‘ 不计入字符串长度。QByteArray字符串的内部编码是不固定的,比如前面QString的toLocal8Bit和toUtf8函数返回的对象全是QByteArray类型。QByteArray字符串的数据来源可能有:

  • 源代码里的字符串,这时QByteArray内码与源文件的编码有关,UTF-8编码源文件生成的很可能就是UTF-8编码的字符串。
  • 本地文本文件,从文件读取的字符串与该文件使用的字符编码有关,Linux上常用UTF-8,而Windows经常使用ANSI多字节编码,Windows简体中文系统一般是GBK,而繁体中文默认是Big5.
  • 网页数据,网页本身也是文本文件,有自己的文本编码格式,这时网页文件编码格式决定QByteArray字符串的编码格式。

我们这里示范的是第一种,全部用UTF-8编码的QByteArray字符串。QByteArray类关于字符串处理的成员函数基本和QString类一样,函数名和参数都是类似的。但是注意因为QByteArray内码不固定,它没有arg函数,也没有字符编码转换的函数。QByteArray关于字符串处理的函数就不枚举了与上一大节QString的差不多,下面直接看示例代码:

void TestStr() //内码 UTF-8 {
    //数值与字符串转换
    int nDec = 800;
    QByteArray basDec;
    basDec.setNum(nDec);    //数值转字符串
    qDebug()<<basDec;
    QByteArray basReal = "125.78999";
    double dblReal = basReal.toDouble();    //字符串转数值
    qDebug()<<fixed<<dblReal;

    //运算符
    QByteArray basABCD = "ABCD";
    QByteArray basXYZ = "XYZ";
    qDebug()<<(basABCD < basXYZ);   //二者字符编码一致才能比较!
    qDebug()<<(basABCD == basXYZ);
    qDebug()<<(basABCD >= basXYZ);
    qDebug()<<(basABCD + basXYZ);

    //子串处理
    QByteArray basHanzi = "1234打印汉字";
    //作为字符串时 QByteArray::length() 和 qstrlen() 一致
    qDebug()<<basHanzi.length()<<"\t"<<qstrlen( basHanzi.data() );
    //重复
    QByteArray basMoreHanzi = basHanzi.repeated(2);
    qDebug()<<basMoreHanzi.count("1234"); //统计次数
    qDebug()<<basMoreHanzi.startsWith("1234");  //开头判断
    qDebug()<<basMoreHanzi.endsWith("汉字");     //结尾判断
    qDebug()<<basMoreHanzi.indexOf("1234");   //从左边查出现位置
    qDebug()<<basMoreHanzi.lastIndexOf("1234"); //从右边查出现位置
    //替换
    basMoreHanzi.replace("1234", "一二三四");
    qDebug()<<basMoreHanzi;

    //切割字符串
    QByteArray basComplexFile = "   /home/user/somefile.txt  \t\t ";
    QByteArray basFileName = basComplexFile.trimmed();  //剔除两端空白
    qDebug()<<basFileName;
    //分隔得到新的 QByteArray 对象列表
    QList<QByteArray> baList = basFileName.split(‘/‘);
    //打印
    for(int i=0; i<baList.length(); i++)
    {
        qDebug()<<i<<"\t"<<baList[i];
    }
    //没有段落函数
}

上面测试函数第一段是数值与字符串互相转换的,比较简单,打印结果是:

"800"

125.789990

浮点数转换时,定点计数法和科学计数法都是可以接受的,上面示范的是定点数。这些函数声明和功能都可以查阅 QByteArray 类的帮助文档。

第二段代码是运算符函数的,需要注意的是一定要在确定字符串内部字符编码的情况下,才能进行比较和拼接,上面用的全是 UTF-8     。不能将不同编码格式的字符串比较,因为得到的结果没意义,反而会造成误导。上面比较运算符的打印结果为:

true

false

false

"ABCDXYZ"

第三段是子串查询处理的,注意只有当 QByteArray 作为字符串处理时,它的 length() 函数计算的长度才会和全局函数 qstrlen( )计算的结果一致。子串部分打印的结果为:

16          16

2

true

true

0

16

"一二三四打印汉字一二三四打印汉字"

上面示范的 basMoreHanzi.replace("1234", "一二三四") ,这种形式的替换函数会对所有匹配的子串进行替换,它的声明是:

QByteArray & replace(const char * before, const char * after)

如果要对指定位置的子串替换,需要换一个声明形式的 replace 函数,比如:

QByteArray & replace(int pos, int len, const char * after)

这个函数会对指定位置 pos 开始的长度为 len 的子串进行替换,这个函数声明只做一次替换。
        对于 replace 函数,必须注意字符编码的问题,UTF-8 的英文字符占用 1 字节,汉字通常是 3 字节,这种不确定性在替换函数和其他分隔子串函数时尤其需要注意,因为 3 字节的汉字如果被截断,就成错误的字符,造成信息损失。因此尽量不要用 QByteArray 类来处理字符串,尤其是涉及分割和替换的。QString 类的字符长度是固定的,所以最适合做字符串处理。

最后一段代码是子串分隔的,trimmed 函数功能也是去除两端的空白区域,split 函数将字符串分隔为多个子串之后按照QList<QByteArray> 类型返回,QList 是一个模板类,QList<QByteArray> 就是存储多个QByteArray 对象的列表,可以直接用中括号 [] 访问里面的各个对象。最后一段代码打印的结果如下:

"/home/user/somefile.txt"

0     ""

1     "home"

2     "user"

3     "somefile.txt"

分隔结果与上一节 QString 是一样的,对于开头 ‘/‘ 左边没有字符的情况,一样会分出来一个空字符串对象。因为一般用 QString 来处理文本字符串,QByteArray 类没有 section 函数,所以字符串处理时优先用QString类。

时间: 2024-10-12 08:54:16

Qt学习(14)的相关文章

Qt学习总结-ui篇(二)

qccs定义圆角 border-radius:10px; 如果想给特定位置定义圆角,如: 左上角:border-left-top-radius:10px; 右下角色:border-right-bottom-rasius:10px; 半透明效果 只需要在css中使用rgba(100,100,100,40)这种形式来表示颜色即可. 为可执行文件添加图标 1.新建文件:finename.rc 文件名无所谓,只要后缀为rc就可以. 2.编辑新建的文件,输入以下内容: IDI_ICON1 ICON DIS

【qt学习006】Dialogs and MainWindows 小结

学习<c++GUI Programming with Qt 4>已有一段时间,非常享受这本书的阅读过程,内容简洁清晰,让人一目了然. 马上要学习更难的内容,所以先做个总结,然后再继续前进. 总结的形式尽量简洁,以代码为主,再将一些我认为重要的笔记作为注释添加在代码中.内容大多是摘抄自书本,但也有一些地方属于个人理解. 闲话少谈,下面列出代码: ? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 // example1

Qt学习之路

  Qt学习之路_14(简易音乐播放器) Qt学习之路_13(简易俄罗斯方块) Qt学习之路_12(简易数据管理系统) Qt学习之路_11(简易多文档编辑器) Qt学习之路_10(Qt中statusBar,MessageBox和Timer的简单处理) Qt学习之路_9(Qt中Item Widget初步探索) Qt学习之路_8(Qt中与文件目录相关操作) Qt学习之路_7(线性布局和网格布局初步探索) Qt学习之路_6(Qt局域网聊天软件) Qt学习之路_5(Qt TCP的初步使用) Qt学习之路

QT学习之路(1):彩票绝对不中模拟器

//============================================//绝对不中,彩票开奖模拟器#include "mainwindow.h"#include "ui_mainwindow.h"#include <QHash>#include <QDebug>MainWindow::MainWindow(QWidget *parent) :    QMainWindow(parent),    ui(new Ui::M

qt学习(三):鼠标图标改变

qt学习 (三):鼠标图标改变 当你进入一个美好的qt软件场景,比如游戏,电脑的黑白图标会让程序逊色不少, 1改图标要加光标的头文件, 2 载入光标图, 3 再设置改光标就可以了 1在头文件中加 #include <QtGui>  //光标类的父类 //再在public成员中声明换的函数void keyPressEvent(QKeyEvent *k); //声明按键换图的函数         .h文件    --注意头文件和声明 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

【qt学习005】搞不明白的布局

记录一下自己在布局这一章遇见的各种狗屎问题. 问题主要出现在布局最后一节:综合布局实例,类似于一个qq管理器的界面(见下图1).看见这个时,打算动手实现一下,于是开始写代码,写着写着发现不知道怎么写了,遇见一些无法解决的问题(问题中描述的布局类之间的关系见下图2): 1. 最底层应该使用哪一类? 2. 怎么将QListWidget加入到最底层? 3. 怎么往QStackWidget加入三个页面,每个页面代表不同的信息? 4. 怎么将QHBoxLayout中的CLOSE按钮连接到退出函数,要完整地

【Qt学习笔记】13.拖放技术:Drag & Drop

1.接受拖放 Drag & Drop 是一个界面操作,用于在两个窗口间传递数据. Drag Source: 拖放源窗口 Drag Target: 拖放目标窗口 拖放操作: 1.在源窗口:选中目标,按下鼠标,移动,拖至目标窗口(Drag) 2.在目标窗口:取消鼠标,到指定位置,松开鼠标(Drop) (按下ESC取消操作) MIME: MIME(Multipurpose Internet Mail Extensions)被传递的数据以MIME格式传送,它是多组type-data数据:(type0,

QT学习第1天

QT学习第一天  坚持住!! 一 Qt概述 1.Qt发展历史 (1)1991年诞生(Haavard Nord/Eirik Chambe-Eng), (2)1994年创立Troll Tech(奇趣科技) (3)2005年QT4.0 (4)2008年被Nokia收购 (5)2009年源代码开源 (6)2012年Nokia将全部QT业务和知识产权卖给Digia公司 (7)2013年QT5.0 QT5.1 QT5.2 (8)2014年Digia公司成立 The Qt Company子公司 2.Qt5.4

QT学习之路--创建一个对话框

Q_OBJECT:这是一个宏,凡是定义信号槽的类都必须声明这个宏. 函数tr()全名是QObject::tr(),被他处理过的字符串可以使用工具提取出来翻译成其他语言,也就是做国际化使用. 对于QT学习之路:Qt学习之路(7):创建一个对话框(上)这个程序.编译出现 invalid use of incomplete type ‘class QPushButton’ findButton->setEnabled(!text.isEmpty()); ^ In file included from