应使用 QDirIterator 实现递归遍历,避免 QDir::entryInfoList() 递归调用导致的栈溢出与性能问题;需设置 QDirIterator::Subdirectories 标志及 QDir::Files | QDir::Dirs | QDir::NoDotAndDotDot 过滤器,next() 返回完整路径。

直接用 QDirIterator,别用 QDir::entryInfoList() 递归调用——后者容易栈溢出、性能差、还难控制深度。
QDirIterator 递归遍历文件和子目录
这是 Qt 官方推荐的高效方式,底层用迭代器避免递归调用,支持深度控制和实时过滤。
-
QDirIterator::Subdirectories是开启递归的关键标志,不加它就只扫当前层 - 过滤器要显式写全:
QDir::Files | QDir::Dirs | QDir::NoDotAndDotDot,漏掉QDir::NoDotAndDotDot会把.和..当成真实目录反复进入 -
next()返回的是相对路径拼接后的完整路径(如/home/user/a/b.txt),不是文件名;需要路径信息就直接用,别再自己拼 - 如果只要文件不要目录,把过滤器换成
QDir::Files | QDir::NoDotAndDotDot即可
QDirIterator it("/path/to/root",
QDir::Files | QDir::Dirs | QDir::NoDotAndDotDot,
QDirIterator::Subdirectories);
while (it.hasNext()) {
QString path = it.next();
QFileInfo fi(path);
if (fi.isFile()) {
qDebug()
<h3>QDir::entryInfoList() 只适合单层遍历</h3>
<p>这个函数本身不支持递归,强行用它做多层遍历必须手动写递归函数,极易出问题。</p>
- 每次调用
entryInfoList()都会一次性读取并缓存当前目录下所有条目,大目录下内存占用陡增 - 递归调用时若没检查
isDir()就直接传入QDir(fileInfo.filePath()),遇到权限不足或符号链接会崩溃或死循环 - 排序和过滤必须提前设置:
dir.setFilter(...)和dir.setSorting(...),否则返回结果不可控 - 想按修改时间倒序排文件?得配
QDir::Time | QDir::Reversed,光写QDir::Time是正序
常见错误:权限拒绝、符号链接、路径编码
实际跑起来卡住或崩溃,八成是这几个地方没处理:
- Linux/macOS 下访问
/proc或/sys这类虚拟文件系统,QDirIterator会触发Permission denied错误,但默认不抛异常——得靠it.fileInfo().exists()或捕获qWarning日志判断 - Windows 上启用
QDirIterator::FollowSymlinks可能导致无限循环(比如软链接指向父目录),生产环境建议关掉 - 路径含中文或特殊字符时,确保源文件用 UTF-8 编码,且 Qt 构建时启用了
iconv或icu支持,否则QDir构造可能静默失败 -
QDir::entryList()返回的名称是原始字节解码后的QString,但某些 NAS 或网络盘返回的文件名编码不标准,fileName()可能乱码,此时应优先用filePath()+QFileInfo
什么时候该用 QDir 而不是 QDirIterator
如果你只需要当前目录下的文件列表、要排序、要分页、或者要配合 QFileSystemModel 做界面绑定,QDir 更合适。
-
QDir::entryInfoList()返回QFileInfoList,天然适配QAbstractItemModel子类的数据源 - 需要按大小/时间/名称动态重排?
setSorting()比手动 sortQStringList稳定得多 - 要过滤特定后缀(比如只看
.log和.txt)?用setNameFilters({"*.log", "*.txt"}),比正则快且安全 - 注意:
setNameFilters必须搭配setFilter(QDir::Files)才生效,单独设没用
真正麻烦的从来不是“怎么写出来”,而是“怎么在用户各种奇怪路径、权限、编码、挂载点下不崩、不卡、不出错”。QDirIterator 的构造参数顺序、过滤器组合、错误静默机制,这些细节不踩一遍坑根本记不住。尤其是 QDir::NoDotAndDotDot 这个 flag,漏一次,整个遍历就进死循环。











