QT 文件或目录拷贝,线程、进度条

文件/或目录拷贝,在子线程中实现,可实时通知拷贝进度

#ifndef SYSTEMFILECOPY_H
#define SYSTEMFILECOPY_H

#include <QObject>

class QThread;
class SystemFileCopy : public QObject
{
    Q_OBJECT
public:
    SystemFileCopy(const QString& SourcePath, const QString& TargetPath);

    void SetInterrupt(bool interrupt) {m_bInterrupt = interrupt;}
    void startThread();

protected slots:
    void startCopy();

signals:
    void sig_copyProgress(qint64 bytesCopyed, qint64 total); //拷贝进度
    void sig_startCopy(const QString& fileName);    //单个文件开始拷贝
    void sig_finshedCopy(const QString& targetPath, bool result); //单个文件拷贝结束信号
    void sig_errorInfo(const QString& errorString); //错误信息
    void sig_finished(bool bSuccess); //拷贝结束信号

private:
    bool detailFileInfo(const QString& from, const QString& target, QStringList& fromFileList, QStringList& toFileList);
private:
    QString m_sSourcePath; //源目录/文件
    QString m_sTargetPath;  //目标目录
    QThread *m_pThread;
    bool m_bInterrupt;      //是否中断取消
};

#endif // SYSTEMFILECOPY_H
#include "systemfilecopy.h"
#include <QFileInfo>
#include <QDir>
#include <QFile>
#include <qthread.h>

#define COPY_SIZE 1024*1024*4
SystemFileCopy::SystemFileCopy(const QString& SourcePath, const QString& TargetPath)
    :m_sSourcePath(SourcePath),
      m_sTargetPath(TargetPath),
      m_pThread(new QThread),
      m_bInterrupt(false)
{
    moveToThread(m_pThread);
    connect(m_pThread, &QThread::started, this, &SystemFileCopy::startCopy);
    connect(this, &SystemFileCopy::sig_finished, m_pThread, &QThread::quit);
    connect(m_pThread, &QThread::finished, m_pThread, &QThread::deleteLater);
}

void SystemFileCopy::startCopy()
{
    QStringList fromList, targetList;
    if(!detailFileInfo(m_sSourcePath, m_sTargetPath, fromList, targetList))
    {
        emit sig_finished(false);
        return;
    }
    int nSize = fromList.size();
    if(nSize != targetList.size() || nSize == 0)
    {
        emit sig_finished(false);
        return;
    }

    qint64 totalSize = 0, writeTotal = 0;
    foreach (const QString& var, fromList) {
        totalSize+=QFileInfo(var).size();
    }

    for(int i = 0; i < nSize; ++i)
    {
        const QString& targetPath = targetList.at(i);
        QDir tmpDir(QFileInfo(targetPath).absoluteDir());
        if(!tmpDir.exists())
        {
            tmpDir.mkpath(tmpDir.path());
        }

        QFile sourceFile(fromList.at(i));
        if(!sourceFile.open(QIODevice::ReadOnly))
        {
            emit sig_errorInfo(sourceFile.errorString());
            sourceFile.close();
            continue;
        }

        QFile targetFile(targetPath);
        if(QFile::exists(targetPath))
            QFile::remove(targetPath);
        if(!targetFile.open(QIODevice::WriteOnly))
        {
            emit sig_errorInfo(targetFile.errorString());
            targetFile.close();
            continue;
        }

        emit sig_startCopy(sourceFile.fileName());
        qint64 sourceSize = sourceFile.size();
        while(sourceSize)
        {
            if(m_bInterrupt)
            {
                emit sig_finished(true);
                return;
            }

            QByteArray byteArry =  sourceFile.read(COPY_SIZE);
            qint64 writeSize = targetFile.write(byteArry);
            if(byteArry.size() == writeSize)
            {
                writeTotal += writeSize;
                sourceSize -= writeSize;
                emit sig_copyProgress(writeTotal, totalSize);
            }
        }
        sourceFile.close();
        targetFile.close();
        emit sig_finshedCopy(targetPath, true);
    }

    emit sig_finished(true);
}


void SystemFileCopy::startThread()
{
    m_pThread->start();
}

bool SystemFileCopy::detailFileInfo(const QString& from, const QString& target, QStringList& fromFileList, QStringList& toFileList)
{
    /*if(!QFileInfo(target).isDir())
        return  false;*/

    QFileInfo SourceInfo(from);
    if(!SourceInfo.exists())
        return  false;

    if(SourceInfo.isDir())
    {
        QString tmpPath = target +"/" + SourceInfo.fileName();
        QFileInfoList fileInfoList(QDir(from).entryInfoList());
        foreach (const QFileInfo& var, fileInfoList) {
            if(!var.fileName().compare(".") ||!var.fileName().compare(".."))
                continue;
            if(var.isDir())
            {
                if(!detailFileInfo(var.filePath(), tmpPath, fromFileList, toFileList))
                    return false;
            }
            else
            {
            	fromFileList << SourceInfo.filePath();
        		toFileList << target+"/"+SourceInfo.fileName()
            }
        }
    }
    else
    {
        fromFileList << SourceInfo.filePath();
        toFileList << target+"/"+SourceInfo.fileName();
    }
    return  true;
}

``使用方式:

```cpp
SystemFileCopy* pCopy = new SystemFileCopy("D:/abc", "D:/ded");
pCopy->startThread();

类中有信号,可根据需要自行连接

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值