将 QDirIterator 移植到 QDirListing
在 Qt 6.8 中添加了QDirListing 作为QDirIterator 更有效的替代(后者目前仍然可用)。本页强调了将QDirIterator 移植到QDirListing 时应注意的一些要点。
在QDirIterator 中,您可以使用两个独立枚举器(QDirIterator::IteratorFlags 和QDir::Filters )中的标志来控制列出哪些条目,而QDirListing 只有一组标志来处理这项任务。
将QDirIterator::IteratorFlags 移植到QDirListing::IteratorFlags 非常简单:
- QDirListing::IteratorFlag::Default 等同于QDirIterator::NoIteratorFlags
- QDirListing::IteratorFlag::FollowDirSymlinks 等同于QDirIterator::FollowSymlinks
- QDirListing::IteratorFlag::Recursive 等同于QDirIterator::Subdirectories
将QDir::Filters 移植到QDirListing::IteratorFlags 可能会更复杂,这取决于您使用的QDir::Filters 的位顺时针 OR-ed 组合。
- 默认情况下,QDirListing 列出目录、常规文件、符号链接和特殊(其他)文件系统条目;你可以使用各种 QDirListing::IteratorFlag::Exclude* 标志,根据条目的类型将其排除在外。
- QDirQDirListing::IteratorFlag::Exclude* 的默认过滤器是QDir::AllEntries ,相当于
using F = QDirListing::IteratorFlag; QDirListing::IteratorFlags(F::ExcludeOther|F::ResolveSymlinks|F::IncludeDotAndDotDot);
- 默认情况下,QDirListing 列出(Windows)驱动器,因此没有与之对应的QDir::Drives.
- QDir::Readable QDir::Writable QDir::Executable QDir::AllDirs QDirListing如果需要此功能,可使用 range-for 循环遍历条目,并根据需要进行筛选。
QDirIterator dit(dirPath, QDir::AllEntries | QDir::Readable | QDir::Executable | QDir::NoDotAndDotDot); while (dit.hasNext()) { const QFileInfo fi = dit.nextFileInfo(); fileNames.append(fi.fileName()); ... } using F = QDirListing::IteratorFlags; for (const auto &dirEntry : QDirListing(dirPath, F::Default)) { const QFileInfo fi = dirEntry.fileInfo(); // Filter based on readable and executable bits if (fi.isReadable() && fi.isExecutable()) { fileNames.append(dirEntry.fileName()); ... } }
// QDir::AllDirs causes dirs to always be listed regardless of `nameFilters`; // for example, to list ".so" files in a file dialog and still list all dirs: QDirIterator dit(dirPath, nameFilters, QDir::AllDirs | QDir::NoDotAndDotDot); while (dit.hasNext()) { const QFileInfo fi = dit.nextFileInfo(); ... } // Equivalent code using QDirListing: using F = QDirListing::IteratorFlags; for (const auto &dirEntry : QDirListing(dirPath, F::Default)) { const QFileInfo fi = dirEntry.fileInfo(); if (fi.isDir() || fi.fileName().endsWith(".so"_L1)) { ... } }
- QDirListing 将QDir::NoDot 、QDir::NoDotDot 和QDir::NoDotAndDotDot 的语义合并为一个标志。默认情况下,QDirListing 不会列出特殊条目
.
和..
。设置QDirListing::IteratorFlag::IncludeDotAndDotDot 可列出它们。
符号链接
默认情况下,除非设置了 QDir::NoSymlinks,否则QDirIterator 会解析符号链接;而除非设置了QDirListing::IteratorFlag::ResolveSymlinks ,否则QDirListing 不会解析符号链接,在这种情况下,过滤是根据符号链接目标的类型而不是符号链接本身来完成的。例如,要只列出常规文件和指向常规文件的符号链接,必须设置QDirListing::IteratorFlag::FilesOnly 和 QDirListing::IteratorFlag::ResolveSymlinks 。
// Symbolic links are resolved by default QDirIterator dit(dirPath, QDir::Files | QDir::NoDotAndDotDot); while (dit.hasNext()) { const QFileInfo fi = dit.nextFileInfo(); fileNames.append(fi.fileName()); ... } // To preserve the behavior of the code above, set ResolveSymlinks: using F = QDirListing::IteratorFlags; for (const auto &dirEntry : QDirListing(dirPath, F::FilesOnly | F::ResolveSymlinks)) { fileNames.append(dirEntry.fileName()); ... }
QDirListing::DirEntry
QDirListing::DirEntry 提供了QFileInfo 的 API 子集(例如,fileName()、filePath()、exists())。DirEntry API 的主要优势在于,如果我们已经通过其他方式获得了所需信息,就可以延迟调用(相当昂贵的)stat()
或lstat()
。例如,在 Linux 上,我们在内部使用 readdir() 遍历目录树,并在返回的信息中获取条目的名称和类型。因此,如果只需要文件名,请使用QDirListing::DirEntry::fileName() 而不是QDirListing::DirEntry::fileInfo().fileName() (QDirListing 将在内部构建一个QFileInfo ,并在需要时透明地使用该文件名)。
© 2025 The Qt Company Ltd. Documentation contributions included herein are the copyrights of their respective owners. The documentation provided herein is licensed under the terms of the GNU Free Documentation License version 1.3 as published by the Free Software Foundation. Qt and respective logos are trademarks of The Qt Company Ltd. in Finland and/or other countries worldwide. All other trademarks are property of their respective owners.