Qt_day7_文件IO

目录

文件IO

[1. QFileDialog 文件对话框(熟悉)](#1. QFileDialog 文件对话框(熟悉))

[2. QFileInfo 文件信息类(熟悉)](#2. QFileInfo 文件信息类(熟悉))

[3. QFile 文件读写类(掌握)](#3. QFile 文件读写类(掌握))

[4. UI操作与耗时操作(掌握)](#4. UI操作与耗时操作(掌握))

[5. 多线程(掌握)](#5. 多线程(掌握))

[5.1 复现未响应](#5.1 复现未响应)

[5.2 创建并启动线程](#5.2 创建并启动线程)

[5.3 异步刷新](#5.3 异步刷新)

[5.4 停止线程](#5.4 停止线程)

[6. 数据持久化(掌握)](#6. 数据持久化(掌握))


文件IO

本章主要使用Qt配合UI实现文件IO的功能,编程目标是实现一个文件拷贝器。

1. QFileDialog 文件对话框(熟悉)

与QMessageBox一样,QFileDialog继承了QDialog,是一个用于选择要打开或保存的文件(目录)的模态对话框。

因此也使用静态成员函数进行弹窗,对话框的结果(选择的文件或目录的路径)也通过返回值表达。

cpp 复制代码
// 获得要打开或保存的单文件路径
// 参数1:父窗口
// 参数2:windowTitle属性
// 参数3:打开窗口时所在的路径,默认为构建目录
// 参数4:文件类型过滤器
// 返回值:选择的文件路径,选择失败返回空字符串
QString QFileDialog::​getOpen(Save)FileName(
                        QWidget * parent = 0, 
                        const QString & caption = QString(), 
                        const QString & dir = QString(), 
                        const QString & filter = QString())

需要注意的是,QFileDialog是一个纯UI类,本身不具备任何IO能力。

通过网盘分享的文件:Day5_24072_Copy (2).zip

链接: https://pan.baidu.com/s/1vu6lqbYWGXf3vDGNF8Aqig 提取码: 2dxs

--来自百度网盘超级会员v7的分享

2. QFileInfo 文件信息类(熟悉)

此类的使用只需要获得对象后调用各种成员函数返回所需信息即可,包括但不限于以下函数:

cpp 复制代码
// 构造函数
// 参数:文件路径
QFileInfo::​QFileInfo(const QString & file)
cpp 复制代码
// 上次修改日期和时间
// 返回值:包含修改日期和时间的QDateTime对象
QDateTime QFileInfo::​lastModified() const
cpp 复制代码
// 返回文件大小的字节数,访问失败返回0
qint64 QFileInfo::​size() const
cpp 复制代码
// 返回文件的可读性
bool QFileInfo::​isReadable() const

通过网盘分享的文件:Day5_24072_Copy (3).zip

链接: https://pan.baidu.com/s/1rRtGatf7XkXDZn0Q050bhQ 提取码: acej

--来自百度网盘超级会员v7的分享

3. QFile 文件读写类(掌握)

QFile类间接继承了QIODevice类,QIODevice是Qt所有IO类的基类,内部包含了最基础的IO接口。

QFile类可以对文件和目录进行IO操作,本节中标记QIODevice类的函数在后续其他派生类中通用。

相关函数如下:

cpp 复制代码
// 构造函数
// 参数为文件路径
QFile::​QFile(const QString & name)
cpp 复制代码
// 打开读写流
// 参数:打开模式
// 返回值:打开是否成功
bool QIODevice::​open(OpenMode mode)  
cpp 复制代码
// 判断数据流是否处于尾部
bool QIODevice::​atEnd() const
cpp 复制代码
// 读取数据
// 参数:一次性读取的最大字节数
// 返回值:携带读取数据的字节数组,QByteArray是Qt的字节数组类
QByteArray QIODevice::​read(qint64 maxSize)
cpp 复制代码
// 写出数据
// 参数:要写出的数据
// 返回值:实际写出的写出的字节数,-1表示错误
qint64 QIODevice::​write(const QByteArray & byteArray)
cpp 复制代码
// 关闭流
void QIODevice::​close()
cpp 复制代码
// 清空输出缓存区
// 返回值为是否成功
bool QFileDevice::​flush()
cpp 复制代码
// 返回流数据的字节数
qint64 QIODevice::​size() const

通过网盘分享的文件:Day5_24072_Copy (4).zip

链接: https://pan.baidu.com/s/1x1z03C3QOh5L-w62pkZoow 提取码: fmx4

--来自百度网盘超级会员v7的分享

【思考】为何上面的代码在处理大文件时有时候会卡顿?

线程阻塞。

4. UI操作与耗时操作(掌握)

在默认情况下,Qt只有一个线程,也被成为主线程(UI线程),此线程主要的任务保证Qt程序正常执行、UI正常显示与交互。

但是一些耗时操作(例如IO或其他复杂算法),如果在主线程中执行,就会导致主线程原本的工作被阻塞,程序就会出现"假死"状态。

操作系统检测到程序出现"假死"状态,并不能确定程序是真死还是假死,因此弹窗让用户自行判断。

5. 多线程(掌握)

5.1 复现未响应

使用线程类QThread的睡眠函数可以非常简单且精准的模拟阻塞:

cpp 复制代码
// 强制当前线程睡眠一段时间
// 参数为睡眠的秒数
void QThread::​sleep(unsigned long secs)

通过网盘分享的文件:Day6_24072_QThread.zip

链接: https://pan.baidu.com/s/1VfOpkZnVHkNKWPz0AIcEHw 提取码: y1f8

--来自百度网盘超级会员v7的分享

5.2 创建并启动线程

创建并启动一个子线程的操作步骤如下:

  1. 选中项目名称,鼠标右键,点击"添加新文件"。

  2. 按照下图所示进行操作。

  1. 设置继承结构。
  1. 项目管理界面,直接点击"完成"。可以看到对应的文件。
  1. 自定义线程类的头文件和源文件还需要修改。
  1. 进入自定义线程类的头文件,覆盖基类QThread的run函数。
复制代码
// 此函数相当于子线程的主函数,调用start函数后,新创建的线程自动调用此函数。`
`void ` `QThread::​run()`                `[protected` `virtual]`
`
  1. 在run函数的函数体中,编写子线程要执行的逻辑。需要注意的是,子线程不能执行任何UI操作,如果子线程的run函数需要用到UI的相关参数,需要主线程(父对象)给子线程(子对象)传参(成员函数)。

  2. 在主线程中创建子线程对象,并调用start函数启动子线程。

cpp 复制代码
// 启动子线程
// 参数:子线程的优先级
void QThread::​start(Priority priority = InheritPriority) [slot]

通过网盘分享的文件:Day6_24072_QThread (2).zip

链接: https://pan.baidu.com/s/1USSDUQ7S8vyuKn4kO0vr3A 提取码: 79v7

--来自百度网盘超级会员v7的分享

5.3 异步刷新

在实际的开发中,两个线程通常要进行数据交互,相比于5.2节,更常见的场景是异步刷新。异步刷新指的是,子线程执行耗时操作,主线程根据子线程耗时操作的参数在UI进行刷新。

异步刷新问题可以归纳为子线程给主线程传参问题,即子对象给父对象传参------信号槽。

通过网盘分享的文件:Day6_24072_QThread (3).zip

链接: https://pan.baidu.com/s/1UwbCf3XG8q8jE5dP2Vvlcg 提取码: zenk

--来自百度网盘超级会员v7的分享

5.4 停止线程

停止线程的一些方法:

  • 调用terminate函数
cpp 复制代码
// 强行停止线程,比较危险,不推荐使用
void QThread::​terminate()                        [slot]
  • 使用标志位

可以在耗时的循环体中添加标志位,通过停止循环间接让run函数执行完,达到停止线程的效果。

通过网盘分享的文件:Day6_24072_QThread (4).zip

链接: https://pan.baidu.com/s/1VrWJBN5ArcEVKI_sg4mkSw 提取码: fztv

--来自百度网盘超级会员v7的分享

【任务】

  1. 实现多线程文件拷贝器,解决大文件卡顿问题。

通过网盘分享的文件:Day5_24072_Copy (5).zip

链接: https://pan.baidu.com/s/1aS-L9ezNivvfiHJwHeluHw 提取码: i3u3

--来自百度网盘超级会员v7的分享

  1. 自学数据库,并完成数据库的电子词典作业。

Qt数据库 · 华清远见工作空间 《Qt数据库》

6. 数据持久化(掌握)

数据持久化:将内存中的数据模型转换为存储模型,以及将存储模型转换为内存中的数据模型的统称。

之前数据库就是一种数据持久化的方式,但是虽然嵌入式使用的SQLite数据库已经是轻量级数据库,但是相对于其他技术,还是一种比较"重"的数据持久化方式。

Qt中提供比数据库更轻量级的数据持久化方式------QSettings

相关函数如下:

cpp 复制代码
// 构造函数
// 参数1:存储文件的名称,默认为构建目录
// 参数2:存储格式
// 参数3:父对象
QSettings::​QSettings(const QString & fileName, Format format, QObject * parent = 0)
cpp 复制代码
// 设置INI文件的编码,建议使用UTF-8
// 参数:编码字符串
void QSettings::​setIniCodec(const char * codecName)
cpp 复制代码
// 开始存储,相同类型数据建议使用此函数,以数组方式存储
// 参数:数组的名称
void QSettings::​beginWriteArray(const QString & prefix)
cpp 复制代码
// 开始存储,不同类型的数据建议使用此函数(相同类型也可以,但是性能不如上面的好),以组方式存储
// 参数:组的名称
void QSettings::​beginGroup(const QString & prefix)
cpp 复制代码
// 在组中添加键值对
// 参数1:键
// 参数2:值
void QSettings::​setValue(const QString & key, const QVariant & value)
cpp 复制代码
// 结束数组/组的存储
void QSettings::​endArray()
void QSettings::​endGroup()
cpp 复制代码
// 根据键获得值
// 参数1:键
// 参数2:如果取出失败的默认值
// 返回值:值
QVariant QSettings::​value(const QString & key, const QVariant & defaultValue = QVariant()) const

通过网盘分享的文件:Day7_24072_QSettings.zip

链接: https://pan.baidu.com/s/16KOWXPZ7Lc1UnA07HycQLw 提取码: 22ky

--来自百度网盘超级会员v7的分享

相关推荐
翔云API2 小时前
PHP开发示例-vin码识别接口-引领汽车行业数字化新风向
开发语言·php
ac-er88882 小时前
如何对PHP的API接口权限认证
开发语言·php
菜鸟、小高2 小时前
从0开始学PHP面向对象内容之(常用魔术方法续一)
开发语言·php
yezipi耶不耶3 小时前
Rust 所有权机制
开发语言·后端·rust
六月悉茗5 小时前
【C语言 - 简易架构】
c语言·开发语言
凡人的AI工具箱5 小时前
15分钟学 Go 第 49 天 :复杂项目开发
开发语言·人工智能·后端·算法·golang
FFDUST5 小时前
C++ 优先算法 —— 四数之和(双指针)
c语言·开发语言·c++·算法·leetcode·1024程序员节
小周不摆烂6 小时前
Java基础-内部类与异常处理
java·开发语言
大鲤余6 小时前
Rust开发一个命令行工具(一,简单版持续更新)
开发语言·后端·rust
梦想画家6 小时前
快速学习Serde包实现rust对象序列化
开发语言·rust·序列化