Qt 之遍历文件夹(经典详解)


前言

关于 Qt 操作文件夹、文件的知识用途较多,比如遍历下一层乃至所有子孙文件、文件夹,获取它们的一些信息(大小、类型、最后更改时间等)。当然,也可以进行级联删除。
首先看简单的:

一、Qt 遍历文件夹下一层的文件:

1、方式 1:

void ImageTree::addFolderImages(QString path)
{
    // 判断路径是否存在
    QDir dir(path);
    if(!dir.exists())
    {
        return;
    }
    dir.setFilter(QDir::Files | QDir::NoSymLinks);
    QFileInfoList list = dir.entryInfoList();

    int file_count = list.count();
    if(file_count <= 0)
    {
        return;
    }

    QStringList string_list;
    for(int i=0; i<file_count; i++)
    {
        QFileInfo file_info = list.at(i);
        QString suffix = file_info.suffix();
        if(QString::compare(suffix, QString("png"), Qt::CaseInsensitive) == 0)   
        {   
            QString absolute_file_path = file_info.absoluteFilePath();
            string_list.append(absolute_file_path);
        }
    }
}

分析:遍历文件的下一层,对于系统而言包括:文件夹、文件、快捷方式,使用 setFilter 即可过滤。通过 entryInfoList 则可以获取过滤后所得到的文件夹下的文件信息列表,遍历文件通过操作 QFileInfo 可得到所需的文件详细信息(大小、类型、后缀等)。

2、方式2:

void ImageTree::addFolderImages(QString path)
{
    // 判断路径是否存在
    QDir dir(path);
    if(!dir.exists())
    {
        return;
    }

    QStringList filters;
    filters<<QString("*.jpeg")<<QString("*.jpg")<<QString("*.png")<<QString("*.tiff")<<QString("*.gif")<<QString("*.bmp");
    dir.setFilter (QDir::Files | QDir::NoSymLinks); // 设置类型过滤器,只为文件格式
    dir.setNameFilters (filters);  // 设置文件名称过滤器,只为 filters 格式(后缀为.jpeg 等图片格式)

    int dir_count = dir.count();
    if(dir_count <= 0)
    {
        return;
    }
    
    QStringList string_list;
    // 获取分隔符
    //QChar separator = QDir::separator();
    QChar separator = QChar('/');
    if(!path.contains(separator))
    {
        separator = QChar('\\');
    }
    QChar last_char = path.at(path.length()-1);
    if(last_char == separator)
    {
        separator = QChar();
    }
    
    for(uint i=0; i<dir_count; i++)
    {
        QString file_name = dir [i];  // 文件名称
        QString file_path = path + separator + file_name;   // 文件全路径
        string_list.append(file_path);
    }

    //string_list 添加完成之后,就可以查看 list 中的文件路径了
}

分析:setNameFilters 顾名思义,就是过滤文件名称的。如果只需要获取指定路径下的文件名,则可去掉 “获取分隔符” 部分代码(因为我是为了获取文件的全路径)。

思考:QDir::separator () 这是用于获取分隔符的,调试过程中发现 path 的分隔符为 ‘/’,奇怪的是获取到的为 ‘\’,刚好相反,所以我通过 contains 的方式获取分隔符的(无非 ‘/’ 与 ‘\’)。

讨论:如果设定 filters 后,那么存在一定的问题。熟用 Windows 的应该都知道,文件名是忽略大小写的(包括扩展名),那么若 filters 设定了 “.jpg” 之后,则就不可添加扩展名为 “.JPG”、“.Jpg” 等大小写兼有的文件了。
既然有问题,就有解决问题的方式。
1、问题来源是由扩展名引起,那么去掉 setNameFilters (filters);
2、上述已经获取文件全路径,那么 QFileInfo file_info(file_path)获取文件信息的对象
3、通过 file_info.suffix () 或者 completeSuffix () 来判定文件的后缀、扩展名
4、获取之后比较时忽略大小写即可。如:QString::compare (suffix, QString ("
.jpeg"), Qt::CaseInsensitive) == 0

总结:通过以上两种方式比较,关于遍历下一层的方式,采用 “方式 1” 较好。

二、级联遍历文件夹及其子孙文件夹中的文件

1.方式1:

void ImageTree::addSubFolderImages(QString path)
{
    // 判断路径是否存在
    QDir dir(path);
    if(!dir.exists())
    {
        return;
    }

    // 获取所选文件类型过滤器
    QStringList filters;
    filters<<QString("*.jpeg")<<QString("*.jpg")<<QString("*.png")<<QString("*.tiff")<<QString("*.gif")<<QString("*.bmp");

    // 定义迭代器并设置过滤器
    QDirIterator dir_iterator(path,
        filters,
        QDir::Files | QDir::NoSymLinks,
        QDirIterator::Subdirectories);
    QStringList string_list;
    while(dir_iterator.hasNext())
    {
        dir_iterator.next();
        QFileInfo file_info = dir_iterator.fileInfo();
        QString absolute_file_path = file_info.absoluteFilePath();
        string_list.append(file_path);
    }
}

分析:QDirIterator 定义过程中可设置过滤器,包括:文件名称、文件类型等。dir_iterator.next () 这句话很重要,如果缺少将会进入死循环!

2.方式2:

QStringList string_list;
void ImageTree::addSubFolderImages(QString path)
{
    QDir dir(path);
    if(!dir.exists())
    {
        return;
    }
    dir.setFilter(QDir::Dirs | QDir::Files | QDir::NoSymLinks);
    dir.setSorting(QDir::DirsFirst);
    QFileInfoList list = dir.entryInfoList();
    int i = 0;
    bool is_dir;
    do
    {
        QFileInfo file_info = list.at(i);
        if(file_info.fileName() == "." | file_info.fileName() == "..")
        {
            i++;
            continue;
        }

        is_dir = file_info.isDir();
        if(is_dir)
        {
            // 进行递归
            addSubFolderImages(file_info.filePath());
        }
        else
        {
            // 获取文件后缀并获取所选包含类型,若存在包含类型且后缀相同,则添加
            QString suffix =  file_info.suffix();
            if(QString::compare(suffix, QString("png"), Qt::CaseInsensitive) == 0)   
            {   
                QString absolute_file_path = file_info.absoluteFilePath();
                string_list.append(absolute_file_path);
            }
        }
        i++;
    }
    while(i<list.size());
}

分析:此方式采用递归的思路解决,也是网上大多数人用的办法,个人建议摒弃!递归的效率真心不敢接受,而且代码看起来也费劲。

总结:通过以上两种方式比较,关于遍历子孙文件夹的方式,采用 “方式 1” 较好。

3.关于 QFileInfo 获取文件信息的方法可以查看 API

void setFile(const QString &file);
void setFile(const QFile &file);
void setFile(const QDir &dir, const QString &file);
bool exists() const;
void refresh();

QString filePath() const;
QString absoluteFilePath() const;
QString canonicalFilePath() const;
QString fileName() const;
QString baseName() const;
QString completeBaseName() const;
QString suffix() const;
QString bundleName() const;
QString completeSuffix() const;

QString path() const;
QString absolutePath() const;
QString canonicalPath() const;
QDir dir() const;
QDir absoluteDir() const;

bool isReadable() const;
bool isWritable() const;
bool isExecutable() const;
bool isHidden() const;
bool isNativePath() const;

bool isRelative() const;
inline bool isAbsolute() const { return !isRelative(); }
bool makeAbsolute();

bool isFile() const;
bool isDir() const;
bool isSymLink() const;
bool isRoot() const;
bool isBundle() const;

QString readLink() const;
inline QString symLinkTarget() const { return readLink(); }

QString owner() const;
uint ownerId() const;
QString group() const;
uint groupId() const;

bool permission(QFile::Permissions permissions) const;
QFile::Permissions permissions() const;

qint64 size() const;

QDateTime created() const;
QDateTime lastModified() const;
QDateTime lastRead() const;

bool caching() const;
void setCaching(bool on);
  • 9
    点赞
  • 57
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值