目录操作(QDir类)及展示系统文件实战
QT 目录操作(QDir 类)及展示系统文件实战
QDir 是 Qt 中用于目录操作的核心类,提供了跨平台的方式来访问目录结构、操作路径、遍历文件等。它使用 / 作为统一的目录分隔符,Qt 会自动将其转换为底层操作系统的分隔符。
文章目录
一、常用 API 速查
1.1 构造与路径操作
| API | 说明 |
|---|---|
QDir() |
构造指向当前工作目录的 QDir |
QDir(const QString &path) |
构造指向指定路径的 QDir |
path() |
获取当前路径(可能是相对路径) |
setPath(const QString &path) |
设置新路径 |
absolutePath() |
获取绝对路径 |
canonicalPath() |
获取规范路径(解析符号链接,消除 . 和 ..) |
dirName() |
获取目录名(绝对路径中最后一个元素) |
isAbsolute() / isRelative() |
判断路径是绝对还是相对 |
makeAbsolute() |
将相对路径转为绝对路径 |
isRoot() |
判断是否为根目录 |
isReadable() |
判断目录是否可读 |
1.2 目录导航
| API | 说明 |
|---|---|
cd(const QString &dirName) |
进入子目录(类似 shell 的 cd) |
cdUp() |
返回上级目录(等价于 cd("..")) |
说明:
cd()和cdUp()改变的是 QDir 对象内部记录的路径,不影响操作系统的工作目录。
1.3 目录创建与删除
| API | 说明 |
|---|---|
mkdir(const QString &dirName) |
创建单个子目录(父目录必须存在) |
mkpath(const QString &dirPath) |
递归创建多级目录(自动创建不存在的父目录) |
rmdir(const QString &dirName) |
删除空目录 |
rmpath(const QString &dirPath) |
递归删除空目录(从最深层开始) |
removeRecursively() |
删除目录及其所有内容(⚠️ 慎用!不可逆) |
rename(const QString &oldName, const QString &newName) |
重命名目录 |
exists() |
判断目录是否存在 |
isEmpty(QDir::Filters) |
判断目录是否为空 |
refresh() |
从磁盘重新读取目录数据 |
1.4 文件与目录内容遍历
| API | 说明 |
|---|---|
entryList(filters, sortFlags) |
获取目录下所有条目的文件名列表(QStringList) |
entryInfoList(filters, sortFlags) |
获取目录下所有条目的详细信息列表(QFileInfoList) |
count() |
获取目录中条目数量 |
operator[](int) |
按索引获取条目名称 |
filePath(const QString &fileName) |
拼接相对路径 |
absoluteFilePath(const QString &fileName) |
拼接绝对路径 |
relativeFilePath(const QString &fileName) |
获取相对于当前目录的路径 |
remove(const QString &fileName) |
删除指定文件 |
1.5 过滤器与排序
| API | 说明 |
|---|---|
setFilter(QDir::Filters filters) |
设置属性过滤器 |
setNameFilters(const QStringList &filters) |
设置名称过滤器(通配符模式) |
setSorting(QDir::SortFlags sort) |
设置排序方式 |
1.6 常用静态方法
| API | 说明 |
|---|---|
QDir::current() / QDir::currentPath() |
应用程序的工作目录 |
QDir::home() / QDir::homePath() |
用户主目录 |
QDir::root() / QDir::rootPath() |
根目录 |
QDir::temp() / QDir::tempPath() |
系统临时目录 |
QDir::setCurrent(const QString &path) |
设置应用程序工作目录 |
QDir::cleanPath(const QString &path) |
清理路径(去除多余的 / 和 ..) |
QDir::toNativeSeparators(const QString &path) |
转换为本地路径分隔符(如 Windows 的 \) |
QDir::fromNativeSeparators(const QString &path) |
从本地分隔符转为 / |
QDir::separator() |
返回平台原生路径分隔符(静态) |
QDir::match(filter, fileName) |
测试文件名是否匹配通配符模式 |
QDir::match(filters, fileName) |
同时测试多个通配符模式 |
QDir::drives() |
返回系统所有逻辑驱动器列表 |
QDir::isAbsolutePath(path) / isRelativePath(path) |
判断路径类型(静态) |
1.7 遍历模式(iterator)
Qt 还提供了 QDirIterator 用于更灵活的递归遍历:
| API | 说明 |
|---|---|
QDirIterator(path, filters, flags) |
构造目录迭代器 |
hasNext() |
是否还有下一个条目 |
next() |
前进到下一个条目,返回文件路径 |
fileName() |
获取当前条目文件名 |
filePath() |
获取当前条目完整路径 |
fileInfo() |
获取当前条目的 QFileInfo |
遍历标志:
| 标志 | 说明 |
|---|---|
QDirIterator::NoIteratorFlags |
默认(不递归) |
QDirIterator::Subdirectories |
递归遍历所有子目录 |
QDirIterator::FollowSymlinks |
跟随符号链接 |
// 递归遍历示例
QDirIterator it("/path/to/dir", QDir::Files, QDirIterator::Subdirectories);
while (it.hasNext()) {
it.next();
qDebug() << it.filePath();
}
二、Filter 过滤器枚举详解
QDir::Filter 用于 entryList() 和 entryInfoList() 过滤条目,可以用 | 组合使用:
| 枚举值 | 说明 |
|---|---|
QDir::Dirs |
列出目录 |
QDir::AllDirs |
列出所有目录,不对目录名过滤 |
QDir::Files |
列出文件 |
QDir::Drives |
列出逻辑驱动器(Unix 下忽略) |
QDir::NoSymLinks |
不列出符号链接 |
QDir::NoDotAndDotDot |
不列出 . 和 .. |
QDir::NoDot |
不列出 . |
QDir::NoDotDot |
不列出 .. |
QDir::AllEntries |
列出所有条目(Dirs | Files | Drives) |
QDir::Readable |
只列出有读权限的条目 |
QDir::Writable |
只列出有写权限的条目 |
QDir::Executable |
只列出有执行权限的条目 |
QDir::Hidden |
包含隐藏文件 |
QDir::System |
列出系统文件 |
QDir::CaseSensitive |
过滤器大小写敏感 |
QDir::Modified |
仅列出已修改的文件(与 Qt 资源系统配合) |
常用组合示例:
// 列出所有文件(不含目录和 . / ..)
QDir dir("/home/user");
QStringList files = dir.entryList(QDir::Files | QDir::NoDotAndDotDot);
// 列出所有隐藏文件
QStringList hidden = dir.entryList(QDir::Files | QDir::Hidden | QDir::NoDotAndDotDot);
// 列出所有条目按修改时间排序
QFileInfoList list = dir.entryInfoList(QDir::AllEntries | QDir::NoDotAndDotDot,
QDir::Time | QDir::Reversed);
三、SortFlag 排序枚举详解
| 枚举值 | 说明 |
|---|---|
QDir::Name |
按名称排序 |
QDir::Time |
按修改时间排序(最新在前) |
QDir::Size |
按文件大小排序 |
QDir::Type |
按文件类型(扩展名)排序 |
QDir::Unsorted |
不排序(保持文件系统原始顺序) |
QDir::DirsFirst |
目录排在文件前面 |
QDir::DirsLast |
目录排在文件后面 |
QDir::Reversed |
反向排序 |
QDir::IgnoreCase |
排序时忽略大小写 |
QDir::LocaleAware |
按本地化规则排序(使用当前区域设置) |
四、案例一:递归计算目录大小
main.cpp
#include <QCoreApplication>
#include <QDir>
#include <QStringList>
#include <QtDebug>
/**
* @brief GetDirFileInfoSizeFunc 递归计算目录下所有文件的总大小
* @param qpath 要计算的目录路径
* @return 该目录下所有文件的字节总数
*/
qint64 GetDirFileInfoSizeFunc(const QString &qpath)
{
// QDir 类专门用来操作路径名称或底层文件系统,
// 可以使用相对或绝对路径来指向一个文件/目录
QDir qdirs(qpath);
qint64 qsize = 0; // 存放目录占据的空间
// QFileInfo 类提供文件系统中文件的名称、路径、位置、访问权限、文件类型等信息
// entryInfoList 获取过滤后目录下的文件信息列表
foreach (QFileInfo finfo, qdirs.entryInfoList(QDir::Files)) {
qsize = qsize + finfo.size();
}
// 递归处理子目录
// QDir::Dirs 列出目录,QDir::NoDotAndDotDot 不列出 . 和 ..
foreach (QString sDir, qdirs.entryList(QDir::Dirs | QDir::NoDotAndDotDot)) {
qsize = qsize + GetDirFileInfoSizeFunc(qpath + QDir::separator() + sDir);
}
// 格式化输出:自动选择合适单位
QString unit = "B";
qint64 currentdirsize = qsize;
if (currentdirsize > 1024) {
currentdirsize = currentdirsize / 1024;
unit = "KB";
}
if (currentdirsize > 1024) {
currentdirsize = currentdirsize / 1024;
unit = "MB";
}
if (currentdirsize > 1024) {
currentdirsize = currentdirsize / 1024;
unit = "GB";
}
if (currentdirsize > 1024) {
currentdirsize = currentdirsize / 1024;
unit = "TB";
}
qDebug().noquote() << "目录占据空间为:" << currentdirsize << unit
<< "\t" << qPrintable(qpath);
return qsize;
}
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
QString strPath = QDir::currentPath(); // 获取当前工作目录
qDebug() << "当前目录为:" << strPath << endl;
// 调用此函数计算目录占据空间的大小
GetDirFileInfoSizeFunc(strPath);
return a.exec();
}
效果:



五、案例二:简易文件浏览器
dialog.h
#ifndef DIALOG_H
#define DIALOG_H
#include <QDialog>
#include <QListWidget> // 列表框
#include <QListWidgetItem>
#include <QLineEdit> // 单行输入框
#include <QDir> // 目录操作
#include <QFileInfo> // 文件信息
#include <QFileInfoList>
#include <QVBoxLayout>
#include <QIcon>
#include <QStringList>
/**
* @brief Dialog 主窗口类
*
* 一个基于 QDir 的简易文件/目录浏览器:
* - 顶部 QLineEdit 显示当前所在目录的绝对路径,支持手动输入路径后回车跳转;
* - 下方 QListWidget 列出当前目录下的所有条目(目录在前、文件在后);
* - 双击列表中的任意条目即可进入对应的子目录。
*/
class Dialog : public QDialog
{
Q_OBJECT
public:
Dialog(QWidget *parent = nullptr);
~Dialog();
private:
QLineEdit *fileLineEdit; // 显示当前目录路径
QListWidget *fileListWidget; // 列表框:展示当前目录下的目录和文件
QVBoxLayout *glayout; // 垂直布局管理器
public:
/**
* @brief 将文件信息列表逐项显示到列表框中
* @param list 待显示的文件信息列表
*/
void dispfileinfolist(QFileInfoList list);
public slots:
/**
* @brief 列出指定目录 dir 下的所有条目并显示
* @param dir 目标目录
*/
void dispDir(QDir dir);
/**
* @brief 双击列表项后,进入该项对应的子目录并刷新显示
* @param item 被双击的列表项
*/
void dispDirShow(QListWidgetItem *item);
};
#endif // DIALOG_H
dialog.cpp
#include "dialog.h"
Dialog::Dialog(QWidget *parent)
: QDialog(parent)
{
resize(500, 350);
setWindowTitle("QDir类综合控件应用测试");
// 创建控件:路径输入框(默认根目录 "/")、条目列表框
fileLineEdit = new QLineEdit("/");
fileListWidget = new QListWidget;
// 垂直布局
glayout = new QVBoxLayout(this);
glayout->addWidget(fileLineEdit);
glayout->addWidget(fileListWidget);
// 信号与槽连接
// 回车 → 将输入框内容作为路径,显示其条目
connect(fileLineEdit, SIGNAL(returnPressed()),
this, SLOT(dispDir(QDir)));
// 双击列表项 → 进入对应子目录
connect(fileListWidget, SIGNAL(itemDoubleClicked(QListWidgetItem *)),
this, SLOT(dispDirShow(QListWidgetItem *)));
// 初始显示根目录 "/" 下的所有条目
QString root = "/";
QDir rootDir(root);
QStringList strlist;
strlist << "*"; // 通配符 "*":匹配所有名称
QFileInfoList list = rootDir.entryInfoList(strlist);
dispfileinfolist(list);
}
Dialog::~Dialog()
{
}
/**
* @brief 将文件信息列表逐项添加到列表框中
*
* 目录条目使用文件夹图标,文件条目使用文件图标;
* "." / ".." 等特殊目录也会一并显示(可在 dispDir 中通过
* 指定过滤器 QDir::NoDotAndDotDot 排除)。
*/
void Dialog::dispfileinfolist(QFileInfoList list)
{
fileListWidget->clear(); // 清空列表框,避免重复显示
for (unsigned int i = 0; i < list.count(); i++) {
QFileInfo tempfileinfo = list.at(i);
QString filename = tempfileinfo.fileName();
if (tempfileinfo.isDir()) {
// 目录 → 使用文件夹图标
QIcon ico("E:/qtCodeImg/dir.jpg");
QListWidgetItem *temp = new QListWidgetItem(ico, filename);
fileListWidget->addItem(temp);
} else if (tempfileinfo.isFile()) {
// 文件 → 使用文件图标
QIcon ico("E:/qtCodeImg/file.jpg");
QListWidgetItem *temp = new QListWidgetItem(ico, filename);
fileListWidget->addItem(temp);
}
}
}
/**
* @brief 列出指定目录下的所有条目并显示
*/
void Dialog::dispDir(QDir dir)
{
QStringList strlist;
strlist << "*";
QFileInfoList fileinfolist =
dir.entryInfoList(strlist, QDir::AllEntries, QDir::DirsFirst);
dispfileinfolist(fileinfolist);
}
/**
* @brief 双击列表项后进入对应子目录并刷新
*/
void Dialog::dispDirShow(QListWidgetItem *item)
{
QDir dir;
QString str = item->text(); // 双击的条目名称
dir.setPath(fileLineEdit->text()); // 以当前显示路径为基准
dir.cd(str); // 切换到双击的目录
// 更新路径输入框并刷新列表
fileLineEdit->setText(dir.absolutePath());
dispDir(dir);
}
效果:

六、案例三:获取文件属性
dialog.h
#ifndef DIALOG_H
#define DIALOG_H
#include <QDialog>
#include <QLabel>
#include <QLineEdit>
#include <QCheckBox>
#include <QPushButton>
#include <QFileDialog> // 文件对话框
#include <QFileInfo> // 文件信息
#include <QDateTime>
#include <QHBoxLayout>
#include <QVBoxLayout>
class Dialog : public QDialog
{
Q_OBJECT
public:
Dialog(QWidget *parent = nullptr);
~Dialog();
private:
// 文件路径
QLabel *labelfilename;
QLineEdit *qlineeditfilename;
QPushButton *qpushbuttongetFilename;
// 文件大小
QLabel *labelfilesize;
QLineEdit *qlineeditfilesize;
// 创建时间
QLabel *labelfilecreatetime;
QLineEdit *qlineeditfilecreatetime;
// 修改时间
QLabel *labelfilemoidfytime;
QLineEdit *qlineeditfilemoidfytime;
// 最后访问时间
QLabel *labelfileaccesstime;
QLineEdit *qlineeditfileaccesstime;
// 文件属性复选框
QLabel *qlabelfileattribute;
QCheckBox *qcheckboxfile;
QCheckBox *qcheckboxshide;
QCheckBox *qcheckboxreadable;
QCheckBox *qcheckboxwriteable;
QCheckBox *qcheckboxexecute;
QPushButton *qpushbuttongetfileattributeinfo;
private slots:
void getfilepathandname(); // 打开文件对话框选择文件
void getfileattributeinfo(); // 获取并显示文件属性信息
};
#endif // DIALOG_H
dialog.cpp
#include "dialog.h"
Dialog::Dialog(QWidget *parent)
: QDialog(parent)
{
setWindowTitle("获取文件属性项目实战模块");
labelfilename = new QLabel("文件路径名称");
qlineeditfilename = new QLineEdit;
qpushbuttongetFilename = new QPushButton("打开文件...");
labelfilesize = new QLabel("文件容量大小:");
qlineeditfilesize = new QLineEdit;
labelfilecreatetime = new QLabel("文件创建时间:");
qlineeditfilecreatetime = new QLineEdit;
labelfilemoidfytime = new QLabel("文件修改时间:");
qlineeditfilemoidfytime = new QLineEdit;
labelfileaccesstime = new QLabel("文件访问时间:");
qlineeditfileaccesstime = new QLineEdit;
// 文件属性复选框
qlabelfileattribute = new QLabel("文件属性");
qcheckboxfile = new QCheckBox("文件");
qcheckboxshide = new QCheckBox("隐藏属性");
qcheckboxreadable = new QCheckBox("只读属性");
qcheckboxwriteable = new QCheckBox("只写属性");
qcheckboxexecute = new QCheckBox("执行权限");
qpushbuttongetfileattributeinfo = new QPushButton("获取文件属性的全部信息");
// ========== 布局 ==========
QGridLayout *glayout = new QGridLayout;
glayout->addWidget(labelfilename, 0, 0);
glayout->addWidget(qlineeditfilename, 0, 1);
glayout->addWidget(qpushbuttongetFilename, 0, 2);
glayout->addWidget(labelfilesize, 1, 0);
glayout->addWidget(qlineeditfilesize, 1, 1, 1, 2);
glayout->addWidget(labelfilecreatetime, 2, 0);
glayout->addWidget(qlineeditfilecreatetime, 2, 1, 1, 2);
glayout->addWidget(labelfilemoidfytime, 3, 0);
glayout->addWidget(qlineeditfilemoidfytime, 3, 1, 1, 2);
glayout->addWidget(labelfileaccesstime, 4, 0);
glayout->addWidget(qlineeditfileaccesstime, 4, 1, 1, 2);
// 文件属性标签水平布局
QHBoxLayout *hlayout = new QHBoxLayout;
hlayout->addWidget(qlabelfileattribute);
hlayout->addStretch();
// 复选框水平布局
QHBoxLayout *hlayoutattribute = new QHBoxLayout;
hlayoutattribute->addWidget(qcheckboxfile);
hlayoutattribute->addWidget(qcheckboxshide);
hlayoutattribute->addWidget(qcheckboxreadable);
hlayoutattribute->addWidget(qcheckboxwriteable);
hlayoutattribute->addWidget(qcheckboxexecute);
hlayoutattribute->addStretch();
// 按钮布局
QGridLayout *glayoutbtn = new QGridLayout;
glayoutbtn->addWidget(qpushbuttongetfileattributeinfo);
// 垂直总布局
QVBoxLayout *vlayout = new QVBoxLayout(this);
vlayout->addLayout(glayout);
vlayout->addLayout(hlayout);
vlayout->addLayout(hlayoutattribute);
vlayout->addLayout(glayoutbtn);
// 信号与槽连接
connect(qpushbuttongetFilename, SIGNAL(clicked()),
this, SLOT(getfilepathandname()));
connect(qpushbuttongetfileattributeinfo, SIGNAL(clicked()),
this, SLOT(getfileattributeinfo()));
}
Dialog::~Dialog()
{
}
void Dialog::getfilepathandname()
{
QString filePathName;
filePathName = QFileDialog::getOpenFileName(
this, "打开文件对话框", "/", "files(*)");
qlineeditfilename->setText(filePathName);
}
void Dialog::getfileattributeinfo()
{
QString strfile = qlineeditfilename->text();
QFileInfo qfi(strfile);
// 获取文件属性信息
qint64 filesize = qfi.size(); // 文件大小
QDateTime createtime = qfi.birthTime(); // 创建时间(Qt 6+;Qt 5 用 created())
QDateTime lastModifytime = qfi.lastModified(); // 最后修改时间
QDateTime lastaccesstime = qfi.lastRead(); // 最后访问时间
// 显示到对应输入框
qlineeditfilesize->setText(QString::number(filesize));
qlineeditfilecreatetime->setText(createtime.toString());
qlineeditfilemoidfytime->setText(lastModifytime.toString());
qlineeditfileaccesstime->setText(lastaccesstime.toString());
// 文件属性复选框状态
bool isFile = qfi.isFile();
bool isHidden = qfi.isHidden();
bool isReadable = qfi.isReadable();
bool isWritable = qfi.isWritable();
bool isExecutable = qfi.isExecutable();
qcheckboxfile->setCheckState(isFile ? Qt::Checked : Qt::Unchecked);
qcheckboxshide->setCheckState(isHidden ? Qt::Checked : Qt::Unchecked);
qcheckboxreadable->setCheckState(isReadable ? Qt::Checked : Qt::Unchecked);
qcheckboxwriteable->setCheckState(isWritable ? Qt::Checked : Qt::Unchecked);
qcheckboxexecute->setCheckState(isExecutable ? Qt::Checked : Qt::Unchecked);
}
效果:

七、打包成 EXE 一体文件步骤
7.1 构建 Release 版本
在 Qt Creator 中选择 Release 模式构建项目:

构建后在项目同级目录下会出现一个文件夹:build-项目名-Desktop_Qt_5_12_8_MinGW_32_bit-Release

7.2 下载 Enigma Virtual Box 打包工具
下载地址: https://enigmaprotector.com/en/downloads.html

7.3 使用 Enigma Virtual Box 打包
步骤一: 打开 Enigma Virtual Box,选择要封装的 EXE 主程序:

步骤二: 添加构建输出文件夹:

步骤三: 选择构建好的 Release 文件夹:

步骤四: 确认文件列表(包括 EXE 和所需的 DLL 文件):

步骤五: 设置输出文件名,点击 Process 开始打包:

步骤六: 打包完成后点击 Run 验证程序是否正常运行:

步骤七: 验证通过——生成的即是可独立运行的 EXE 一体文件:

说明: Enigma Virtual Box 将 EXE 和所需 DLL 打包为单个文件,无需安装即可在未装 Qt 环境的 Windows 上运行。如需更精细的控制(如压缩、加密),可考虑使用
windeployqt+ 其他打包工具(如 NSIS、Inno Setup)制作安装包。
小结
QDir 是 Qt 文件系统操作的核心入口,核心要点:
- 路径操作:
QDir使用/作为统一分隔符,自动适配平台;cd()/cdUp()不改变系统工作目录 - 目录管理:
mkdir()/mkpath()创建目录,rmdir()/removeRecursively()删除目录 - 内容遍历:
entryList()返回文件名列表,entryInfoList()返回含详细信息的QFileInfo列表;QDirIterator支持递归遍历 - 过滤器与排序:
QDir::Filter(13种)和QDir::SortFlag(10种)可灵活组合,精确控制输出 - 静态工具方法:
currentPath()/homePath()/tempPath()快速获取标准路径,toNativeSeparators()处理路径格式 - 实战应用: 递归计算目录大小、文件浏览器、文件属性查看,覆盖了
QDir+QFileInfo+QFileDialog的典型组合用法
openEuler 是由开放原子开源基金会孵化的全场景开源操作系统项目,面向数字基础设施四大核心场景(服务器、云计算、边缘计算、嵌入式),全面支持 ARM、x86、RISC-V、loongArch、PowerPC、SW-64 等多样性计算架构
更多推荐


所有评论(0)