阅读QtCreator--常见文件操作的实现

在很多应用中经常都要操作文件的,比如递归/非递归删除文件(夹),拷贝文件夹等,在QtCreator中有一个辅助类完成了这些常用的操作FileUtils,在Utils-libs当中。它实现了以下四个操作

static bool removeRecursively(const QString &filePath, QString *error = 0);
    static bool copyRecursively(const QString &srcFilePath, const QString &tgtFilePath, QString *error = 0);
    static bool isFileNewerThan(const QString &filePath, const QDateTime &timeStamp);
    static QString resolveSymlinks(const QString &path);

下面分别解释一下它们的实现。

bool FileUtils::removeRecursively(const QString &filePath, QString *error)
{
    QFileInfo fileInfo(filePath);//提供系统独立的文件信息,文件名、路径、权限、文件夹(或快捷方式)等。
    //如果不存在该路径,并且该路径也不是快捷方式,就不用删除了
    if (!fileInfo.exists() && !fileInfo.isSymLink())
        return true;
    //设置文件的访问权限(添加用户可写权限)
    QFile::setPermissions(filePath, fileInfo.permissions() | QFile::WriteUser);
    if (fileInfo.isDir())//指定路径是文件夹(或者通过快捷方式链接到一个文件夹)
    {
        QDir dir(filePath);
        dir = dir.canonicalPath();//去掉一些不必要的路径信息,返回绝对路径(返回快捷方式的目标路径)
        if (dir.isRoot())//不能删除根目录(C:,D:...)
        {
            if (error)
            {
                *error = QCoreApplication::translate("Utils::FileUtils",
                    "Refusing to remove root directory.");
            }
            return false;
        }
        //不能删除home(C:/Documents and Settings/Username)
        if (dir.path() == QDir::home().canonicalPath())
        {
            if (error)
            {
                *error = QCoreApplication::translate("Utils::FileUtils",
                    "Refusing to remove your home directory.");
            }
            return false;
        }
        //除了..和.之外的文件夹,文件、快捷方式、隐藏文件、系统文件,
        //这里返回的只有名字,不是完整路径
        QStringList fileNames = dir.entryList(QDir::Files
                                              | QDir::Hidden
                                              | QDir::System
                                              | QDir::Dirs
                                              | QDir::NoDotAndDotDot);

        foreach (const QString &fileName, fileNames)
        {
            //递归删除
            if (!removeRecursively(filePath + QLatin1Char('/') + fileName, error))
                return false;
        }
        //删除空的文件夹
        if (!QDir::root().rmdir(dir.path()))
        {
            if (error)
            {
                *error = QCoreApplication::translate("Utils::FileUtils", "Failed to remove directory '%1'.")
                        .arg(QDir::toNativeSeparators(filePath));
            }
            return false;
        }
    }
    else //说明是文件
    {
        if (!QFile::remove(filePath))
        {
            if (error)
            {
                *error = QCoreApplication::translate("Utils::FileUtils", "Failed to remove file '%1'.")
                        .arg(QDir::toNativeSeparators(filePath));
            }
            return false;
        }
    }
    return true;
}
/*!
    \fn resolveSymlinks()
    \brief 处理快捷方式,iMaxLevel指定最大链接次数
*/
QString FileUtils::resolveSymlinks(const QString &path, const int &iMaxLevel)
{
    QFileInfo f(path);
    int links = iMaxLevel;
    while (links-- && f.isSymLink())
        f.setFile(f.symLinkTarget());
    if (links <= 0)
        return QString();
    return f.filePath();
}
bool FileUtils::copyRecursively(const QString &srcFilePath, const QString &tgtFilePath, QString *error)
{
    QFileInfo srcFileInfo(srcFilePath);
    if (srcFileInfo.isDir())//是文件夹,应该先创建文件夹,然后拷贝里面文件
    {
        QDir targetDir(tgtFilePath);
        targetDir.cdUp();
        //目标文件夹不能存在
        if (!targetDir.mkdir(QFileInfo(tgtFilePath).fileName()))
        {
            if (error)
            {
                *error = QCoreApplication::translate("Utils::FileUtils", "Failed to create directory '%1'.")
                        .arg(QDir::toNativeSeparators(tgtFilePath));
                return false;
            }
        }
        QDir sourceDir(srcFilePath);
        QStringList fileNames = sourceDir.entryList(QDir::Files | QDir::Dirs | QDir::NoDotAndDotDot | QDir::Hidden | QDir::System);
        //深度优先遍历即可
        foreach (const QString &fileName, fileNames)
        {
            const QString newSrcFilePath
                    = srcFilePath + QLatin1Char('/') + fileName;
            const QString newTgtFilePath
                    = tgtFilePath + QLatin1Char('/') + fileName;
            if (!copyRecursively(newSrcFilePath, newTgtFilePath, error))
                return false;
        }
    }
    else
    {
        if (!QFile::copy(srcFilePath, tgtFilePath))
        {
            if (error)
            {
                *error = QCoreApplication::translate("Utils::FileUtils", "Could not copy file '%1' to '%2'.")
                        .arg(QDir::toNativeSeparators(srcFilePath),
                             QDir::toNativeSeparators(tgtFilePath));
            }
            return false;
        }
    }
    return true;
}
/*!
 * \brief FileUtils::isFileNewerThan
 * 比较文件或文件夹是否比某个时间新,如果filePath是文件夹,那么它里面有一个文件比timeStamp新,
 * 就返回真
 */
bool FileUtils::isFileNewerThan(const QString &filePath, const QDateTime &timeStamp)
{
    QFileInfo fileInfo(filePath);
    if (!fileInfo.exists())//如果文件不存在,返回false
        return false;
    if (fileInfo.lastModified() >= timeStamp)//文件修改时间更新
        return true;
    if (fileInfo.isDir())
    {
        //这里不包括隐藏文件、快捷方式等系统文件
        const QStringList dirContents = QDir(filePath)
            .entryList(QDir::Files | QDir::Dirs | QDir::NoDotAndDotDot);
        foreach (const QString &curFileName, dirContents)
        {
            const QString curFilePath
                = filePath + QLatin1Char('/') + curFileName;
            if (isFileNewerThan(curFilePath, timeStamp))
                return true;
        }
    }
    return false;
}

上边的isFileNewerThan中代码与源码不太相同,因为我认为当文件路径不存在时,应该返回false的。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值