C++ Qt数据类型
Qt作为一种跨平台开发工具,具有强大的基本数据类型基础,除了承袭C++和STL数据类型的衣钵,还抽象出大量的Qt特色数据类型支撑以满足应用开发的各种需求。本文记录了常用的一些数据类型,持续更新。
Qt基本数据类型
以下数据类型对应不同位数,用于要求较高的场合;跨平台环境应该避免直接使用int和long,int最常见是32位的,但是也见16位、64位;long在32位系统是32位,相当于int,在64位系统是64位的,相当于long long。
类型 | 大小 | 说明 |
---|---|---|
bool | 8位 | 布尔 |
int8_t/qint8 | 8位 | signed char |
int16_t/qint16 | 16位 | signed short |
int32_t/qint32/int | 32位 | signed int |
int64_t/qint64 | 64位 | long long int |
uint8_t/quint8 | 8位 | unsigned char |
uint16_t/quint16 | 16位 | unsigned short |
uint32_t/quint32 | 32位 | unsigned int |
uint64_t/quint64 | 64位 | unsigned long long int |
float | 16位 | 浮点数 |
double | 32位 | 浮点数 |
const char* | 32位 | 指向字符串常量的指针 |
QString类型
1 | ////增加字符 |
参数格式化打印: 1
2
3
4
5QString test("Info:");
int age = 16;
QString name = "Eden";
test += QString("age=%1 name=%2").arg(QString:: number(age), name);
qDebug() << test; //"Info:age=16 name=Eden"
QStringList方法
类似vector<string>,Qt有容器类型QVector<QString>
,但针对字符串数组Qt抽象出了一种类QStringList
,并且提供了额外的操作接口,方便使用。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26QStringList list1 = {"apple", "banana", "cherry"};
//增加
//operator<<
//append(QString str);
QStringList Person;
Person<<"Eden"<<"Mike"<<"Lucy";
Person.append("Mary");
//删除元素
//removeOne(QString str); //删除第一个匹配str的字符串
//removeAt(int pos); //删除下标pos的字符串
//遍历元素
qDebug()<<Person; //支持输出整个列表,("Eden", "Mike", "Lucy")
for(int i=0; i<Person.length(); i++){
qDebug()<<Person[i]; //逐个遍历
}
// 插入元素
//insert(int pos,QString str); //在pos前插入字符串str
ls1.insert(1,"God");
//查找基本同QString
//int indexOf(QString str,int pos,Qt::CaseSensitive); //从下标pos开始查找str,返回第一个匹配下班,默认CaseSensitive大小写敏感
//int lastIndexOf(QString str,int pos,Qt::CaseSensitive) //反向查找,返回最后一个匹配下标
QSettings写ini文件
ini文件是一种配置文件,当Qt需要与配置交互时,可以使用QSettings进行读写;一个ini配置文件的结构如下,因为ini文件可能是整个项目共享的,因此需要使用Section作为分组(分节)写入和读取,配置项就是简单的键值对。
1
2
3
4
5
6[Section]
key = value
//实例:
[Person]
Eden=18
写操作: 1
2
3
4
5QSettings setting("D:\\Documents\\Desktop\\note\\test.ini",QSettings::IniFormat); //路径,ini配置
setting.beginGroup("Person"); //组
setting.setValue("Eden",18); //键、值
setting.endGroup(); //结束组
读操作:通过键查询值 1
2
3
4
5QSettings rsetting("D:\\Documents\\Desktop\\note\\test.ini",QSettings::IniFormat); //路径,ini配置
rsetting.beginGroup("Person"); //组
int num = rsetting.value("Eden").toInt(); //读取的是QVariant,需要转换
rsetting.endGroup();
qDebug()<<num;
除了ini格式,QSetting还支持NativeFormat
格式,用于读取windows注册表(没用过,鸽掉
遍历读取ini文件: 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37QSettings setting("D:\\Documents\\Desktop\\note\\test.ini",QSettings::IniFormat);
setting.clear(); //清除文件内容
setting.sync(); //同步
setting.beginGroup("Master");
setting.setValue("GesiLa",12);
setting.setValue("KING Kong",100);
setting.endGroup();
setting.beginGroup("Superman");
setting.setValue("Dijia","good");
setting.setValue("GaiYa","commom");
setting.endGroup();
setting.sync(); //同步写入新设置
/*********** 写入文件形如:
* [Master]
GesiLa=12
KING%20Kong=100
[Superman]
Dijia=good
GaiYa=commom
* **********/
//遍历读取
QStringList groups = setting.childGroups();
for(QString& pos:groups){ //得到Section名称:怪兽、超人
setting.beginGroup(pos);
QStringList keys = setting.allKeys(); //遍历每个section的key
for(QString kpos:keys){
qDebug()<<setting.value(kpos).toString();//统一按字符串读出
}
setting.endGroup();
}
QDir、QFile文件操作相关
以下涉及新建目录、创建文本文件、写入文本、复制文件、重命名文件、删除文件、删除目录等;
一个值得重视的点是:当使用QFile::copy(path)
或者QFile::remove(path)
时,如果path
是相对路径,那么是相对Qt工作路径的QDir::currentPath()
,当编译文件夹和目的文件夹不一致时就会导致错误路径操作。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49 QString curDir = QDir::currentPath(); //获取Qt当前工作目录
qDebug()<<curDir;
QDir dir("D:/Documents/Desktop/note"); //dir目录
qDebug()<<dir.path(); //获取QDir对象路径
if(!dir.exists("QDir_test")){ //dir目录下新建目录
if(dir.mkdir("D:/Documents/Desktop/note/QDir_test")) //QDir新建文件夹
qDebug()<<"mkdir Done";
}
else
qDebug()<<"Dir exists";
dir.cd("QDir_test"); //更新QDir,cd会将字符追加到QDir
qDebug()<<dir.path();
QFile new_file(dir.filePath("newfile.txt")); //QFile绑定QDir下的文件
if(new_file.open(QIODevice::ReadWrite|QIODevice::Text)){ //打开才真正创建
QTextStream out(&new_file); //文本流
out<<"Hello World1";
new_file.close();
}
//复制文件newfile.txt到copyfile.txt,且重命名newfile.txt为sourcefile.txt
for(QString& file_name:dir.entryList(QDir::Files)){ //仅遍历文件
if(file_name=="newfile.txt"){
QString et_name = dir.path()+"/"+file_name;
qDebug()<<et_name;
QFile::copy(et_name,dir.path()+"/"+"copyfile.txt"); //复制
new_file.rename("sourcefile.txt");
}
}
dir.mkdir("new_dir");
for(QString& file_name:dir.entryList(QDir::Files|QDir::Dirs)){ //还可以打印子目录
qDebug()<<file_name;
}
//析构步骤,运行上述代码检查是否创建文件成功,最后再运行以下代码:
dir.rmdir("new_dir");
for(QString& file_name:dir.entryList(QDir::Files)){ //删除文件
QFile::remove(dir.path()+"/"+file_name);
}
dir.cd(".."); //返回上层目录
qDebug()<<dir;
dir.rmdir("QDir_test"); //删除父目录
entryList获取文件与目录
1 | //获取所有文件和目录(AllEntries),不包括本目录和上级目录(NoDotAndDotDot),包括隐藏文件和目录(Hidden) |
QDir斜杠、反斜杠转换
1 | //将 '\' 转为 '/'(windows to linux) |
QDir::entryInfoList
如果需要遍历目录下文件、目录、软链接及其路径信息,可以考虑使用QDir::entryInfoList
,具体是:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24QFileInfoList QDir::entryInfoList(
const QStringList &nameFilters = QStringList(),
QDir::Filters filters = QDir::NoFilter,
QDir::SortFlags sort = QDir::NoSort) const
其中:
nameFilters:QStringList对象,表明文件通配符(不是正则表达式),如:
- "*.txt": 匹配所有 .txt 文件
- "doc?.pdf": 匹配如 doc1.pdf, docA.pdf 等
- "[abc].txt": 匹配 a.txt, b.txt, c.txt
- "file[!0-9].dat": 匹配不以数字结尾的 file.dat 文件
filters:文件类型筛选,常用如:
- QDir::Files: 列出文件
- QDir::Dirs: 列出目录
- QDir::NoDotAndDotDot: 不包括 "." 和 ".." 目录
- QDir::AllEntries: 列出所有条目(文件和目录)
sort:排序规则,如
- QDir::Name: 按名称A到Z排序
- QDir::Time: 按时间早到晚排序
- QDir::Size: 按大小小到大排序
- QDir::Type: 按类型A到Z排序
若需要排序颠倒,则QDir::Time | QDir::ReversedQFileInfoList
对象,即QFileInfo
类型的列表,详见后文;
示例: 1
2
3
4
5QDir dir("D:\\Documents\\Desktop\\logtest");
QFileInfoList finfoList = dir.entryInfoList(QStringList() << "*.log"<<"*.exe", QDir::Files, QDir::Time);
for (QFileInfo& pos : finfoList) {
qDebug() << pos.absoluteFilePath();
}
QFileInfo
类型判断
常用三种文件类型判断,普通文件、目录文件、软链接文件:
1
2
3isFile();
isDir();
isSymLink();
Windows软链接与Unix软链接
软链接,又称符号链接;在Unix中(Linux、IOS、macOS)中,软链接指向是真实的文件,打开软链接就是打开对应的文件/目录;
1
2
3
4
5
6
7
QFileInfo info1("/home/bob/bin/untabify"); //创建软链接,链接到/opt/pretty++/bin/untabify
info1.isSymLink(); // 是否软链接,returns true
info1.absoluteFilePath(); // 绝对路径,returns "/home/bob/bin/untabify"
info1.size(); // 软链接大小,returns 56201,同/opt/pretty++/bin/untabify大小
info1.symLinkTarget(); // 真实链接:returns "/opt/pretty++/bin/untabify"1
2
3
4
5
6
7
QFileInfo info1("C:\\Documents and Settings\\Bob\\untabify.lnk"); //lnk文件
info1.isSymLink(); // 是否软链接,Qt认为lnk属于软链接,returns true
info1.absoluteFilePath(); // returns "C:/Documents and Settings/Bob/untabify.lnk"
info1.size(); // returns 743,这里大小就是lnk本身大小,并不指向真实大小
info1.symLinkTarget(); // 真实链接:returns "C:/Pretty++/untabify"
QFileInfo文件名/路径名取法
摘自QFileInfo主要函数详解:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61//相对路径文件:
============================relative file path============================
=================QFileInfo("./user/xueying/script.tag.gz")================
baseName--------------------->>> "script",无后缀文件名
completeBaseName------------->>> "script.tag",带一个后缀文件名
suffix----------------------->>> "gz",最后一个后缀
completeSuffix--------------->>> "tag.gz",完整后缀
path------------------------->>> "./user/xueying",最后一级目录(自行补充分隔符)
filePath--------------------->>> "./user/xueying/script.tag.gz",绝对路径/相对路径
fileName--------------------->>> "script.tag.gz",完整文件名,若为目录为空字符
absolutePath----------------->>> "E:/project/qt/fileinfoTest/bin/user/xueying",绝对路径(自行补充分隔符)
absoluteFilePath------------->>> "E:/project/qt/fileinfoTest/bin/user/xueying/script.tag.gz",绝对路径+完整文件名
absoluteDir().dirName-------->>> "xueying",最后一级目录名称
absoluteDir().absolutePath--->>> "E:/project/qt/fileinfoTest/bin/user/xueying",最后一级目录完整绝对路径(自行补充分隔符)
absoluteDir().path----------->>> "E:/project/qt/fileinfoTest/bin/user/xueying",最后一级目录完整绝对路径(自行补充分隔符)
dir().dirName---------------->>> "xueying",最后一级目录名称
dir().absolutePath----------->>> "E:/project/qt/fileinfoTest/bin/user/xueying",最后一级目录完整绝对路径(自行补充分隔符)
dir().path------------------->>> "./user/xueying",最后一级目录相对路径(自行补充分隔符)
//绝对路径文件基本同上;
//带末尾分隔符的相对路径目录:
=====================relative dir path with QDir::sepator()=====================
==========================QFileInfo("./user/xueying/")==========================
baseName--------------------->>> ""
completeBaseName------------->>> ""
suffix----------------------->>> ""
completeSuffix--------------->>> ""
bundleName------------------->>> ""
path------------------------->>> "./user/xueying",最后一级目录,(自行补充分隔符)
filePath--------------------->>> "./user/xueying/",当前目录路径,(按需补充分隔符)
fileName--------------------->>> ""
absolutePath----------------->>> "E:/project/qt/fileinfoTest/bin/user",当前目录所在的目录绝对路径(上一级目录)(自行补充分隔符)
absoluteFilePath------------->>> "E:/project/qt/fileinfoTest/bin/user/xueying",当前目录绝对路径(自行补充分隔符)
absoluteDir().dirName-------->>> "user"
absoluteDir().absolutePath--->>> "E:/project/qt/fileinfoTest/bin/user"
absoluteDir().path----------->>> "E:/project/qt/fileinfoTest/bin/user"
dir().dirName---------------->>> "xueying"
dir().absolutePath----------->>> "E:/project/qt/fileinfoTest/bin/user/xueying"
dir().path------------------->>> "./user/xueying"
//不带末尾分隔符的相对路径目录:
======================relative dir path no QDir::sepator()======================
============================QFileInfo("./user/xueying")=========================
baseName--------------------->>> "xueying",(1. baseName不为空)
completeBaseName------------->>> "xueying" (1. baseName不为空)
suffix----------------------->>> ""
completeSuffix--------------->>> ""
path------------------------->>> "./user" (2.path截取带末尾分隔符的目录)
filePath--------------------->>> "./user/xueying" (3.filePath有无分隔符取决于原来有没有分隔符)
fileName--------------------->>> "xueying" (4. fileName不为空)
absolutePath----------------->>> "E:/project/qt/fileinfoTest/bin/user"
absoluteFilePath------------->>> "E:/project/qt/fileinfoTest/bin/user/xueying"
absoluteDir().dirName-------->>> "user"
absoluteDir().absolutePath--->>> "E:/project/qt/fileinfoTest/bin/user"
absoluteDir().path----------->>> "E:/project/qt/fileinfoTest/bin/user"
dir().dirName---------------->>> "user"(5. 目录名,以后面是否有斜杠为准,不是xueying)
dir().absolutePath----------->>> "E:/project/qt/fileinfoTest/bin/user"(5. 目录名,以后面是否有斜杠为准,不是xueying)
dir().path------------------->>> "./user" (5. 目录名,以后面是否有斜杠为准,不是xueying)
//绝对路径目录基本同理。
跨平台路径末尾自适应加分隔符,windows
Qt下添加"\",linux
Qt下添加"/": 1
2
3QString srcPath("/usr/root");
if (!srcPath.endsWith(QDir::separator()))
srcPath += QDir::separator(); //末尾加分隔符,"/usr/root/"
QVariant容器
Qt需要进行大量的数据传递,指定一种返回类型可能不能满足数据的传输要求,因此Qt引入QVariant支持各种数据类型;QVariant支持几乎所有的Qt数据类型以及C++基本数据类型,也支持符合要求的自定义类型。
QVariant构造基本数据类型
对于QVariant支持的数据类型,可以直接构造并且赋值,读取时转换为对应类型,也可以使用setValue
函数:
1 | QVariant num(123); |
isValid()
返回true代表初始化类型有效,绑定了某种数据类型对象;isNull
类似的,可以检验对象是否存在;
1
2
3
4
5
6
7
8QVariant test;
qDebug()<<test.isValid(); //false,无绑定
qDebug()<<test.isNull(); //true,Null对象
QVariant test1("");
qDebug()<<test1.type(); //QVariant::QString
qDebug()<<test1.isValid(); //true,绑定QVariant::QString
qDebug()<<test1.isNull(); //false,空字符不为Null
自定义数据类型与fromValue()
fromValue()
和setValue()
功能一致,都是给QVariant
类型赋值,但用法上略有区别;setValue()
是QVariant
的一个成员函数,为已存在的QVariant
对象赋值,而fromValue()
是一个类静态函数,能够在构造的同时完成赋值,并且返回一个新的QVriant
对象,支持更广泛的数据类型,尤其是自定义数据类型。此外,Qt数据类型都在元对象系统中定义,自定义的数据类型需要在定义的结构体/类下方使用宏Q_DECLARE_METATYPE
声明;
读取时,使用QVariant::value
函数可读出指定数据类型数据:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20//头文件定义新数据类型
struct Person{
int id;
QString name;
};
Q_DECLARE_METATYPE(Person)
//cpp文件:
Person person;
person.id = 10;
person.name = "Eden"; //person类实例
QVariant test = QVariant::fromValue(person); //person类型转换到QVariant类型
//从QVariant读取自定义的person类型
if(!test.canConvert<Person>()) //先判断是否可转换
qFatal("Convert illegal!!");
Person rperson = test.value<Person>();
qDebug()<<rperson.id;
qDebug()<<rperson.name;
QList & QVariantList
QList是Qt最常用的容器,是一种双向链表结构,仅列出常见接口:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29QList<QString> lst;
lst<<"elem1"<<"elem2"<<"elem3";
qDebug()<<lst; //("elem1", "elem2", "elem3")
lst.append("elem4"); //尾插,push_back亦可
lst.prepend("elem0"); //头插,push_front亦可
qDebug()<<lst; //("elem0", "elem1", "elem2", "elem3", "elem4")
lst.replace(4,"elem4_rp"); //替换
qDebug()<<lst; //("elem0", "elem1", "elem2", "elem3", "elem4_rp")
QString elem = lst.takeAt(0); //删除并返回下标0
qDebug()<<elem; //"elem0"
qDebug()<<lst; //("elem1", "elem2", "elem3", "elem4_rp")
lst.swap(0,3); //交换
qDebug()<<lst; //("elem4_rp", "elem2", "elem3", "elem1");
lst.insert(0,"elem0"); //指定位置前插入
qDebug()<<lst; //("elem0", "elem4_rp", "elem2", "elem3", "elem1")
lst.removeAt(2); //删除下标2
lst.removeFirst(); //首个字符,同pop_front()
lst.removeLast(); //最后字符,同pop_back()
lst.removeOne("elem0"); //删除第一个匹配项
lst.removeAll(); //同clear()
back() //尾元素
front() //第一个元素;
QVariantList
是QList<QVariant>
的别名类型。
QMap、QHash & QVariantMap、QVariantHash & QMultiHash
Qt的STL延续了C++ STL的大部分特性,但是有一些地方用法却不一样;
QMap
对应C++的map
结构,都是有序的,QHash
对应unordered_map
,是高效的哈希表查找结构,是无序的,区别以下(不完全):
QMap
、QHash
支持value
函数,用于索引某个键的值,而map
、unordered_map
只能使用find(key)
的方式索引迭代器。QMap
、QHash
插入相同的键,不会返回pair迭代器检查是否失败,而是会覆盖相同键的值;QMap
、QHash
的插入支持相同的键,使用成员函数QMap/QHash.insertMulti(key,value)
能够强制插入相同的key;遍历不能直接使用
for(auto pos:QMap)
,这里返回的pos不是QMap/QHash
的迭代器,而是int类型,指向存储的值,因此宜使用普通迭代器方法for(auto i=.begin();i!=.end(); i++)
;map/unordered_map
的迭代器使用pos.first
、pos.second
访问键值,QMap/QHash迭代器使用pos.key()
、pos.value()
访问键值。
QVariantMap
、QVariantHash
分别是QMap<QString, QVariant>
、QHash<QString, QVariant>
的别名;QMultiHash
对应multimap
,insert
函数就支持多个相同键的插入。
value(x,x)
QMap.value(x,x),返回x对应的值,如果键x不存在,返回值为x;
QByteArray
QByteArray
是字节数组,类似char[]或者char*,不同于QString使用UTF-16表示数据(两字节/四字节),每个字符元素是2字节,QByteArray每个字符是8位数据,即0-255,既可以表示128个ASCII码字符,也可以表示原始的字节格式,采用UTF-8编码方式,对char兼容较好,但不直接支持Unicode;
QByteArray常用接口函数
1 | const char* str = "Hello World"; |
插入append/push_back
、prepend/push_front
、insert
等能够插入字符/字符串,用法同QList
,但QByteArray
没有pop
接口,删除相关方法:
1
2
3
4
5byteArray1.remove(0,5); //删除0及其后5个字符
byteArray1.chop(2); //删除尾部2个字节
byteArray1.truncate(2); //仅保留2下标前部分,后面丢弃
clear //清空operator[]
,at(i)
只用于遍历读取场合,不可用于写操作:byteArray1.at(0) = '1'
是非法的。
查找相关接口: 1
2
3
4
5
6
7
8
9
10
11
12
13
14indexOf(char) //同QString
indexOf(char[]) //同QString
lastIndexOf(char) //同QString
lastIndexOf(char[]) //同QString
left(num) //同QString
right(num) //同QString
mid(pos,num) //同QString
//统计字符/字符串
count('x')
count("xx")
contains("xx")
startsWith("xx")
endsWith("xx")
QString、QByteArray、std::string、char*转换
ASCII是8位数据,对应128个早期定义的英文/数字/控制字符;UniCode是为了在全世界建立统一的字符集,约定了每个字符唯一的二进制编码,前128个码仍然沿用ASCII码;
然而UniCode只约定了二进制编码表示,没有具体约束存储方式,UTF-8
使用1字节——3字节存储字符,此外还有UTF-16、32等少用的字符集。
而在QString中,每个符号是一个QChar,QChar使用UTF-16
进行编码,而string
、QByteArray
、char[]
内部均使用8位存储一个字符;
以下将QString按本地八位编码存储转换,使用fromHex进行16进制解析,因此byteArray的第一个16位数字:31被解析成0x49,进而对应数字1的ASCII,hexbyteArray[0]
= '1',后面的解析同理; 1
2
3QString test("31323334");
QByteArray byteArray = test.toLocal8Bit();//转换到QByteArray,8位存储一个字符,如byteArray[0] = '3';
QByteArray hexbyteArray = QByteArray::fromHex(byteArray); //十六进制转换,输出1234
在单字节存储中,Latin1
和UTF-8
是常用的两种编码,也是MySql的两种常用编码;其中Latin1
是严格的单字节存储,就像ASCII
一样,但是ASCII
的最高一位实际上是奇偶校验,而Latin1
实实在在可以表示256种字符,除了兼容ASCII的128种,还支持另外一些控制字符与拉丁字符;
因此,ASCII
码和Latin1
都不具备表示所有字符的能力:
1
2
3QString test("你");
QByteArray byteArray1 = test.toUtf8(); //"\xEF\xBF\xBD\xEF\xBF\xBD"
QByteArray byteArray2 = test.toLatin1(); //"??"
Qt除了兼容QString、QByteArray,支持std、传统的一些字符串类型转换:
1 | QString.toStdString() //QString转std::string |
QJson
记录了Qt的Json封装和解析,包括QJsonDocument、QJsonObject、QJsonValue、QJsonArray类型:
一个示例json: 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15{
"Company": "Digia",
"From": "1991",
"Name": "Qt",
"Page": {
"Developers": "https://www.qt.io/developers/",
"Download": "https://www.qt.io/download/",
"Home": "https://www.qt.io/"
},
"Version": [
4.8,
5.2,
5.7
]
}
1 | //封装出Json: |
QTextStream
Qt除了使用Write读写文件,还支持文本流读写文件: 1
2
3
4
5
6
7
8
9
10
11
12
13
14QFile file("D:\\Documents\\Desktop\\note\\fileTest.log");
if(file.open(QIODevice::WriteOnly|QIODevice::Text)){ //写
QTextStream stream(&file); //绑定对象法一
stream << "Hello World!!";
file.close();
}
//读
if(file.open(QIODevice::ReadOnly|QIODevice::Text)){
QTextStream rstream;
rstream.setDevice(&file); //绑定对象法二
QString output = rstream.readAll();
qDebug()<<output;
file.close();
}
Qt正则匹配
Qt 5以上可使用QRegularExpression:
判断并捕获匹配字段
1
2
3
4
5
6
7
8
9QString test = "Eden,23 years old";
QRegularExpression re("^([a-z]*),(\\d+)", QRegularExpression::CaseInsensitiveOption); //忽略大小写
QRegularExpressionMatch match = re.match(test);
if (match.hasMatch()) {
QString name = match.captured(1); //Eden
int age = match.captured(2).toInt(); //23
qDebug() << name;
qDebug() << age;
}连续匹配
1
2
3
4
5
6
7
8QString test = "Eden 20;Mike 30;Lucy 40;";
QRegularExpression re("(\\d{2})"); //查找2位数字
QRegularExpressionMatchIterator match = re.globalMatch(test); //匹配
while (match.hasNext()) { //连续匹配
QRegularExpressionMatch pos = match.next();
int age = pos.captured(0).toInt();
qDebug() << age; //20 30 40
}匹配替换字符
1
2
3
4QString test = "I am Superman";
QRegularExpression re("\\s([a-z]+)$",QRegularExpression::CaseInsensitiveOption); //忽略大小写,匹配Superman
QString rtest = test.replace(re, " Master"); //替换匹配字段
qDebug() << rtest; //"I am Master"
QProcess
用于新建一个进程,且调用相应exe并获取返回结果;
这里先编译一个text.exe
供给调用: 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
using namespace std;
int calculation(int a,int b){
return a+b;
}
int main(int argc,const char* argv[]){
if (argc!=3){
cout<<"Wrong parameter!!"<<endl;
return -1;
}
cout<<"Your Result is:"<<calculation(stoi(argv[1]),stoi(argv[2]))<<endl;
return 0;
}
在Qt中调用并读取返回结果: 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27QProcess process;
QString exePath("D:/Documents/Desktop/test/test.exe");
QStringList qslParam;
qslParam << "10" << "20"; //参数列表
process.start(exePath, qslParam);
//或者:
//process.setProgram(exePath);
//process.setArguments(qslParam);
//process.start();
if (!process.waitForStarted()) {
qWarning() << "start error";
}
if (!process.waitForFinished()) {
qWarning() << "handle error";
}
QString output = QString::fromUtf8(process.readAll()); //内容转为Utf8编码传入output
qDebug() << output; //"Your Result is:30\r\n"
QRegularExpression re(".*:+(\\d+)"); //匹配数字30
QRegularExpressionMatch match = re.match(output);
if (match.hasMatch()) {
QString result = match.captured(1);
qDebug() << result.toInt(); //30
}
qDebug() << "Done" << endl;
QCryptographicHash哈希加密
QCryptographicHash
采用哈希映射特定文本加密到散列码,散列码字符来自类似base64的字符集(A-Z, a-z, 0-9, +, /)
,具有以下特性:
不可逆:不可能从散列码恢复数据;
长度固定
不唯一性:不同的输入可能导致相同的散列码输出,但是这个哈希碰撞的概率极小。
常用的两种哈希映射方法是sha1
和md5
,可用作文件校验,QCryptographicHash
提供了静态方法和成员函数方法实现散列加密:
1
2
3
4
5
6
7
8
9
10
11
12//法一:静态函数,QCryptographicHash::hash
QByteArray byteArray;
byteArray.append("Hello Eden");
QByteArray hash1 = QCryptographicHash::hash(byteArray, QCryptographicHash::Md5);
QString output1 = hash1.toHex();
qDebug() << output1; //"83e83ec8d3cdffc27620c9ff98335c36"
//法二:addData+result
QCryptographicHash hash2(QCryptographicHash::Md5);
hash2.addData(byteArray);
QString output2 = hash2.result().toHex();
qDebug() << output2; //"83e83ec8d3cdffc27620c9ff98335c36"
md5运算速度更快,而sha1安全略高于md5,但目前md5和sha1均不是绝对安全的,可经过计算机计算破解,所谓破解并不是破获原来的文本,而是找到另一组输入产生相同的散列码输出,即哈希碰撞;可通过多次加密减少哈希碰撞的概率,或使用sha2等更安全的哈希算法。