QDirIterator를 QDirListing으로 포팅하기

Qt 6.8에서는 QDirIterator 을 보다 효율적으로 대체하기 위해 QDirListing 이 추가되었습니다(후자는 현재도 사용 가능합니다). 이 페이지에서는 QDirIteratorQDirListing 로 포팅할 때 유의해야 할 몇 가지 사항을 강조합니다.

QDirIterator 에서는 두 개의 개별 열거자( QDirIterator::IteratorFlagsQDir::Filters)의 플래그를 사용하여 나열되는 항목을 제어할 수 있지만 QDirListing 에서는 이 작업을 처리하는 플래그 세트가 하나만 있습니다.

QDirIterator::IteratorFlagsQDirListing::IteratorFlags 으로 포팅하는 것은 간단합니다:

QDir::FiltersQDirListing::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. 이 기능이 필요한 경우 필요에 따라 범위-포 루프를 사용하여 항목을 반복하고 필터링하세요.
    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::NoDotDotQDir::NoDotAndDotDot 의 의미가 하나의 플래그로 결합되었습니다. 기본적으로 QDirListing 에는 특수 항목인 ... 이 나열되지 않습니다. QDirListing::IteratorFlag::IncludeDotAndDotDot 을 설정하면 해당 항목을 나열합니다.

기본적으로 QDirIterator 은 QDir::NoSymlinks를 설정하지 않으면 심볼릭 링크를 확인하지만 QDirListingQDirListing::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::DirEntryQFileInfo API의 하위 집합을 제공합니다(예: fileName(), filePath(), exists()). 다른 방법으로 필요한 정보를 이미 확보한 경우 (다소 비싼) stat() 또는 lstat() 호출을 지연시키는 것이 DirEntry API의 주요 장점입니다. 예를 들어 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.