QDirIterator から QDirListing への移植

Qt 6.8 では、QDirIterator をより効率的に置き換えるものとして、QDirListing が追加されました(後者は今のところまだ利用可能です)。このページでは、QDirIteratorQDirListing に移植する際の注意点を紹介します。

QDirIterator では、2つの別々の列挙子、QDirIterator::IteratorFlagsQDir::Filters のフラグを使用して、どのエントリがリストされるかを制御できますが、QDirListing では、このタスクを処理するためのフラグが1セットあります。

QDirIterator::IteratorFlags からQDirListing::IteratorFlags への移植は簡単である:

QDir::Filters からQDirListing::IteratorFlags への移植は、使用するQDir::Filters のビット OR の組み合わせによっては、もっと複雑になるかもしれない。

  • デフォルトでは、QDirListing は、ディレクトリ、通常のファイル、シンボリックリンク、および特殊な(その他の)ファイルシステムのエントリをリストします。さまざまな QDirListing::IteratorFlag::Exclude* フラグを使用することで、そのタイプに基づいてエントリを除外することができます。
  • QDirデフォルトのフィルタは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::NoDotQDir::NoDotDotQDir::NoDotAndDotDot のセマンティクスが1つのフラグに統合されている。デフォルトでは、QDirListing は特別なエントリ... をリストしない。QDirListing::IteratorFlag::IncludeDotAndDotDot を設定すると、リストされます。

デフォルトでは、QDirIterator は、QDir::NoSymlinks が設定されない限りシンボリックリンクを解決します。一方、QDirListing は、QDirListing::IteratorFlag::ResolveSymlinks が設定されない限りシンボリックリンクを解決しません。この場合、シンボリックリンク自体ではなく、シンボリックリンクのターゲットのタイプに基づいてフィルタリングが行われます。例えば、通常のファイルと通常のファイルへのシンボリックリンクのみをリストアップするには、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::fileInfo().fileName() ではなく、QDirListing::DirEntry::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.