文件/或目录拷贝,在子线程中实现,可实时通知拷贝进度
#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();
类中有信号,可根据需要自行连接