一、Qt 文件概述
🔥 文件操作是应用程序必不可少的部分。Qt 作为⼀个通用开发库,提供了跨平台的文件操作能力。Qt 提供了很多关于⽂件的类,通过这些类能够对文件系统进行操作,如文件读写、文件信息获取、文件制或重命名等
二、输入输出设备类
在 Qt 中,文件读写的类为 QFile
- QFile 的父类为
QFileDevice
,QFileDevice
提供了文件交互操作的底层功能 QFileDevice
的父类是QIODevice
,QIODevice
的父类为QObject
QIODevice
是 Qt 中所有输入输出设备(input/output device,简称 I/O 设备)的基础类,I/O 设备就是能进行数据输入和输出的设备- 例如文件是⼀种 I/O 设备,网络通信中的
socket
是 I/O 设备,串口、蓝牙等通信接口也是 I/O 设备,所以它们也是从QIODevice
继承来的。
Qt 中主要的⼀些 I/O 设备类的继承关系如下图所示:
名称 | 作用 |
---|---|
QFile | 用于 文件操作和文件数据读写 的类,使用 QFile 可以读写任意格式的文件。 |
QSaveFile | 用于 安全保存文件 的类。是使用 OSaveFile 保存文件时,它会先把数据写入一个临时文件,成功提交后才将数据写入最终的文件。如果保存过程中出现错误,临时文件里的数据不会被写入最终文件,这样就能确保最终文件中不会丢失数据或被写入部分数据。在保存比较大的文件或复杂格式的文件时可以使用这个类,例如从网络上下载文件等。 |
QTemporaryFile | 用于 创建临时文件 的类。使用函数 QTemporaryFile::open() 就能创建一个文件名唯一的临时文件,在 QTemporaryFile 对象被删除时,临时文件被自动删除 |
QTcpSocket QUdpSocket | 分别实现了 TCP 和 UDP 的类。 |
OSerialPort | 实现了 串口通信 的类,通过这个类可以实现计算机与串口设备的通信。 |
QBluetoothSocket | 用于 蓝牙通信 的类。手机和平板计算机等移动设备有蓝牙通信模块,笔记本电脑一般也有蓝牙通信模块。通过 QBluetoothSocket 类,就可以编写蓝牙通信程。如编程实现笔记本电脑与手机的蓝牙通信。 |
QProcess | 用于启动外部程序,并且可以给程序传递参数。 相当于是对 fork / exec 操作进行的封装 |
QBuffer | 以一个 QByteArray 对象作为数据缓冲区,将 QByteArray 对象当作一个 I/0 设备来读写。 |
- 串口:一种比较古老的通信方式,一般是在嵌入式系统上,通过串口和开发板之间进行交互操作
三、文件读写类
在 Qt 中,文件的读写主要是通过 QFile
类来实现。在 QFile
类中提供了一些用来读写文件的方法。对于文件的操作主要有:
- 读数据:QFile 类中提供了多个方法用于读取文件内容;如:read()、readAll()、readLine()等。
- 写数据:QFile 类中提供了多个方法用于往文件中写内容;如 write()、writeData()等。
- 关闭文件:文件使用结束后必须用函数 close()关闭文件。
访问一个设备之前,需要使用 open()
函数 打开该设备,而且必须指定正确的打开模式,QIODevice 中所有的打开模式由 QlODevice::OpenMode
枚举变量定义,其取值如下:
名称 | 说明 |
---|---|
QIODevice::NotOpen | 没有打开设备 |
QIODevice::ReadOnly | 以 只读 方式打开设备 |
QIODevice::WriteOnly | 以 只写 方式打开设备 |
QIODevice::ReadWrite | 以 读写 方式打开设备 |
QIODevice::Append | 以 追加 方式打开设备,数据写到文件末尾 |
QIODevice::Truncate | 每次打开文件后重写文件内容,原内容将被删除 |
QIODevice::Text | 在读文件时,行尾终止符会被转换为 ‘\n’;当写入文件时,行尾终止符会被转换为本地编码。如:Win32上为 ‘\r\n’; |
QIODevice::Unbuffered | 无缓冲形式打开文件,绕过设备中的任何缓冲区 |
QIODevice::NewOnly | 文件存在则打开失败,不存在则创建文件 |
代码如下:
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QPlainTextEdit>
#include <QFileDialog>MainWindow::MainWindow(QWidget *parent): QMainWindow(parent), ui(new Ui::MainWindow)
{ui->setupUi(this);this->setWindowTitle("记事本");QMenuBar* menuBar = this->menuBar();// 获取到菜单项QMenu* menu = new QMenu("文件");// 添加菜单menuBar->addMenu(menu);QAction* ac1 = new QAction("打开"); // 添加菜单项QAction* ac2 = new QAction("保存");menu->addAction(ac1);menu->addAction(ac2);// 指定一个输入框 edit 为全局变量edit = new QPlainTextEdit();QFont font;font.setPixelSize(25);edit->setFont(font);this->setCentralWidget(edit);// 连接 QAction 信号槽connect(ac1, &QAction::triggered, this, &MainWindow::handleAction1);connect(ac2, &QAction::triggered, this, &MainWindow::handleAction2);
}void MainWindow::handleAction1()
{// 1. 先弹出 "打开文件" 对话框,选择打开文件QString path = QFileDialog::getOpenFileName(this);// 2. 把文件名显示到状态栏里QStatusBar* statusBar = this->statusBar();statusBar->showMessage(path);// 3. 根据用户选择路径,构造一个 QFile 对象,并且打开文件QFile file(path);if(!file.open(QIODevice::ReadOnly)){// 打开文件失败statusBar->showMessage(path + " 打开失败");return;}// 4. 读取文件// 这里需要确保打开的文件是文本文件才行// 如果是 二进制文件, 交给 QString,QString text = file.readAll();// 5. 关闭文件,并设置读取内容file.close();edit->setPlainText(text);
}void MainWindow::handleAction2()
{// 1. 先弹出 "打开文件" 对话框,选择打开文件QString path = QFileDialog::getOpenFileName(this);// 2. 显示文件名QStatusBar* statusBar = this->statusBar();statusBar->showMessage(path);// 3. 根据用户选择路径,构造一个 QFile 对象,并且打开文件QFile file(path);if(!file.open(QIODevice::WriteOnly)){statusBar->showMessage(path + " 打开失败");return;}// 4. 写文件const QString& text = edit->toPlainText();file.write(text.toUtf8());file.close();
}MainWindow::~MainWindow()
{delete ui;
}
结果如下:
四、文件和目录信息类
QFilelnfo
是 Qt
提供的一个用于获取文件和目录信息的类,如获取文件名、文件大小、文件修改日期等。QFileInfo
类中提供了很多的方法,常用的有:
方法名称 | 作用 |
---|---|
isDir() | 检查该文件是否是目录 |
isExecutable() | 检查该文件是否是可执行文件 |
fileName() | 获得文件名 |
completeBaseName() | 获取完整的文件名 |
suffix() | 获取文件后缀名 |
completeSuffix() | 获取完整文件后缀 |
size() | 获取文件大小 |
isFile() | 判断是否为文件 |
fileTime() | 获取文件创建时间、修改时间、最近访问时间等 |
#include "widget.h"
#include "ui_widget.h"
#include <QPushButton>
#include <QDebug>
#include <QFileDialog>Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget)
{ui->setupUi(this);QPushButton* button = new QPushButton("查看文件属性", this);connect(button, &QPushButton::clicked, [=](){QString path = QFileDialog::getOpenFileName(this);QFileInfo fileInfo(path); // 构造对象// 打印相关属性qDebug() << fileInfo.fileName();qDebug() << fileInfo.suffix();qDebug() << fileInfo.path();qDebug() << fileInfo.size();qDebug() << fileInfo.isFile();qDebug() << fileInfo.isDir();// ...});
}