Qt/C++使用小记6【qt复制文件夹或剪切文件夹】

第六个小收获

众所周知,window系统有剪切文件夹或者复制文件夹,那么在qt内如何实现呢,之前有过类似的需求,所以记录一下

直接上代码:

首先创建一个拷贝复制剪切文件的线程:
线程.h文件,复制文件肯定是会放到线程中去处理的,这里使用了继承QThread
#ifndef COPYFILETHREAD_H
#define COPYFILETHREAD_H

#include <QThread>

//  拷贝/剪切文件的线程
class CopyFileThread : public QThread
{
    Q_OBJECT
public:
    /**
     * @brief CopyFileThread    构造函数
     * @param strSrcPath        源文件路径
     * @param strDestPath       目标路径
     * @param bIsCut            false否 true是 默认为否
     */
    CopyFileThread(const QString strSrcPath, const QString strDestPath,
                   bool bIsCut = false);
    //  dowork运行线程
    void run() override;

private:

    enum emRunStatus
    {
        COPY_FILE_FAILED = 3001,    //  复制文件失败
        DELETE_FILE_FAILED,         //  删除文件失败
        DESTFILEPATH_IS_SUB,        //  目标文件夹是源文件夹的子文件夹
    };
    /**
     * @brief   CopyDir             复制文件夹内的所有文件
     * @param   strSourceDir        源文件夹
     * @param   strDestinationDir   目标文件夹
     * @return  true成功 false失败
     */
    bool CopyDir(const QString strSourceDir, QString strDestinationDir);

    /**
     * @brief   DeleteDir   删除文件夹内的所有文件
     * @param   strPath     文件夹路径
     * @return  true成功 false失败
     */
    bool DeleteDir(const QString &strDirPath);

    /**
     * @brief   FileNameEqualAddSuffix    文件名重复则添加文件后缀
     * @param   strSamePath               文件路径的引用 输出不重复的文件名
     * @return  true 成功 false失败
     */
    bool FileNameEqualAddSuffix(QString &strSamePath);

signals:
    /**
     * @brief SignalSendProgress    发送进度信号
     * @param iPercent               进度值
     */
    void SignalProgress(const int iPercent);

    /**
     * @brief SignalSendMessage 文本信号传输
     * @param strMessage        告知工作状态内容
     */
    void SignalRunMessage(const QString strMessage);

    /**
     * @brief SignalRunFailed   发送运行失败信号
     * @param uRunStatus        3001复制失败 3002删除失败
     */
    void SignalRunFailed(const emRunStatus uRunStatus);

private:
    /** 源路径(旧路径) */
    QString m_strSourcePath;

    /** 目标路径(新路径) */
    QString m_strDestinatePath;

    /** 是否是剪切文件夹 */
    bool m_bIsCut;
};

#endif // COPYFILETHREAD_H

 所有函数和信号都如上所示

线程.cpp文件
#include "CopyFileThread.h"
#include <QDir>
#include <QFile>
#include <QDebug>

/**
 * @brief CopyFileThread    构造函数
 * @param strSrcPath        源文件路径
 * @param strDestPath       目标路径
 * @param bIsCut            false否 true是 默认为否
 */
CopyFileThread::CopyFileThread(const QString strSrcPath, const QString strDestPath,
                               bool bIsCut):
    m_strSourcePath(strSrcPath),
    m_strDestinatePath(strDestPath),
    m_bIsCut(bIsCut)
{

}

void CopyFileThread::run()
{
    //  路径不同 但是路径在当前源目录内
    if(m_strSourcePath != m_strDestinatePath)
    {
        int iSrcSize = m_strSourcePath.size();
        QString strTempDest = m_strDestinatePath.left(iSrcSize);
        qDebug()<<strTempDest;
        if(strTempDest == m_strSourcePath)
        {
            qDebug()<<u8"目标文件夹是源文件夹的子文件夹!";
            emit SignalRunFailed(DESTFILEPATH_IS_SUB);
            return;
        }
    }

    //  复制文件
    bool bRetCopyDir = CopyDir(m_strSourcePath,m_strDestinatePath);
    if(!bRetCopyDir)
    {
        qDebug()<< __FUNCTION__ <<"copy file fail!";
        //  发送失败位置
        emit SignalRunFailed(COPY_FILE_FAILED);
        return;
    }

    if(m_bIsCut)
    {
        //  若是剪切则调用删除文件函数
        bool bRetDeleteDir = DeleteDir(m_strSourcePath);
        if(!bRetDeleteDir)
        {
            qDebug() << __FUNCTION__ << "delete file fail!";
            //  发送失败位置
            emit SignalRunFailed(DELETE_FILE_FAILED);
            return;
        }
    }

    return;
}

/**
 * @brief   CopyDir             复制文件夹内的所有文件
 * @param   strSourceDir        源文件夹
 * @param   strDestinationDir   目标文件夹
 * @return  true成功 false失败
 */
bool CopyFileThread::CopyDir(const QString strSourceDir, QString strDestinationDir)
{
    bool  bRNT = true;

    QDir sourceDir(strSourceDir);
    QDir destDir(strDestinationDir);

    //  若目标文件夹不存在 则创建
    if(!destDir.exists())
    {
        destDir.mkdir(strDestinationDir);
    }
    else
    {
        //  存在则添加目标文件名后缀
        FileNameEqualAddSuffix(strDestinationDir);
        destDir.mkdir(strDestinationDir);
    }

    //  获取文件路径
    QFileInfoList list = sourceDir.entryInfoList();
    foreach(auto info,list)
    {
        if(info.fileName() == "." || info.fileName() == "..")
        {
            continue;
        }
        if(info.isDir())
        {
            //创建文件夹,调用递归
            //要添加这句if判断 不然只要复制的话 会无限递归
            if(strDestinationDir != info.filePath())
            {
                bRNT = CopyDir(info.filePath(),strDestinationDir + "/" + info.fileName());
            }
            continue;
        }

        //文件拷贝
        QFile file(info.filePath());
        bRNT = file.copy(strDestinationDir + "/" + info.fileName());
    }

    return bRNT;
}

/**
 * @brief   DeleteDir   删除文件夹内的所有文件
 * @param   strPath     文件夹路径
 * @return
 */
bool CopyFileThread::DeleteDir(const QString &strDirPath)
{
    bool bRNT = true;

    //  容错处理 是否传入了空的路径||路径是否存在
    if(strDirPath.isEmpty() || !QDir().exists(strDirPath))
    {
        bRNT = false;
        return bRNT;
    }

    //  获取文件属性
    QFileInfo FileInfo(strDirPath);
    //如果是文件
    if(FileInfo.isFile())
    {
        //  删除文件
        QFile::remove(strDirPath);
    }
    else if(FileInfo.isDir())   //如果是文件夹
    {
        QDir qDir(strDirPath);
        //  删除文件夹
        qDir.removeRecursively();
    }

    return bRNT;
}

/**
 * @brief   FileNameEqualAddSuffix    文件名重复则添加文件后缀
 * @param   strSamePath               文件路径的引用 输出不重复的文件名
 * @return  true 成功 false失败
 */
bool CopyFileThread::FileNameEqualAddSuffix(QString &strSamePath)
{
    bool bRTN = true;

    int iNum = 1;
    //  若有中文乱码 记得处理下
    strSamePath += u8" - 副本";
    QString tempStrPath = strSamePath;
    QDir destDir(strSamePath);

    //  若存在则一直改变iNum的值
    while(destDir.exists())
    {
        ++iNum;
        strSamePath = tempStrPath + " (" + QString::number(iNum) + ")";
        destDir.setPath(strSamePath);
    }

    return bRTN;
}
 最后运行示例
#include "CopyFileThread.h"

//  假设要将"D:/NewData/data3"拷贝到D:下
//  路径根据需求处理
QString strSource("D:/NewData/data3");
//  若此时想拷贝到D盘 且选择了D盘
QString strDest("D:");
//  则要对目标文件夹做处理
QStringList strList = strSource.split("/");
strDest += "/" + strList.last();
//  ↑这样拼接一下就是D:/data3了↑ 实际情况实际处理

//  第一个参数为目标文件夹 第二个参数为新的文件夹
CopyFileThread *pCopyFileThread = new CopyFileThread(strSource, strDest);
//    启动线程
pCopyFileThread->start();

//    线程释放
connect(pCopyFileThread,&CopyFileThread::finished,pCopyFileThread,&CopyFileThread::deleteLater);
connect(pCopyFileThread,&CopyFileThread::finished,this,[=]{
    qDebug()<<u8"线程运行完毕,内存已释放";
});

运行测试文件内容:

测试文件内有三个文件data1.txt、data2.txt和文件夹data3,data3文件夹内有一个文件data3.txt

运行结果

可以看见复制成功,如果是剪切,则可以在实例化线程的构造函数内将第三个参数改为true,切换为剪切即可,这样源文件在复制完之后会删除。文件名处理也需要自己完善,上述只是示例

  • 5
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值