16,212
社区成员
发帖
与我相关
我的任务
分享
QFile::copy(src, dst);
qDebug() << "hello";
struct MoveInfo {
bool rm;
QString src;
QString dst;
};
enum TAG {
COUNT_FILE = 0,
HANDLE = 1,
};
static QSemaphore freeSpace(8); // 控制任务队列缓冲长度
static QSemaphore usedSpace(0);
static QQueue<MoveInfo> task_q;
class Producer : public QThread
{
Q_OBJECT
public:
Producer(QObject *parent=nullptr);
~Producer();
void run();
void setParams(QString, QString, bool);
signals:
void mainMsgChanged(QString, QColor c=Qt::black);
void subMsgChanged(QString);
void completed();
private:
QString root_path;
int total = 0;
int count = 0;
QString src_path;
QString dst_path;
bool rm;
void walkPath(QString, QString, TAG);
};
Producer::Producer(QObject *parent)
:QThread (parent)
{
}
void Producer::run()
{
qDebug().noquote() << "Source path:" << src_path;
total = 0;
count = 0;
emit mainMsgChanged(tr("正在统计数量..."));
walkPath(src_path, dst_path, TAG::COUNT_FILE);
qDebug().noquote() << "Total number of files:" << total;
count = 0;
emit mainMsgChanged(tr("正在处理..."));
walkPath(src_path, dst_path, TAG::HANDLE);
emit mainMsgChanged(tr("Ready"));
if(total != 0)
emit subMsgChanged(QString("[%1%] %2/%3").arg(int(100*((float)count/total))).arg(count).arg(total));
else
emit subMsgChanged(QString("[%1%] %2/%3").arg(100).arg(count).arg(total));
// 没有更多文件了,放入空信息通知消费线程退出
MoveInfo info;
for (int i = 0; i < 8; i++)
{
freeSpace.acquire();
task_q.enqueue(info);
usedSpace.release();
}
}
void Producer::walkPath(QString src, QString dst, TAG t)
{
QDir src_dir(src);
QDir dst_dir(dst);
QFileInfoList src_files = src_dir.entryInfoList(QStringList{"*.xls"}, QDir::Files | QDir::NoDotAndDotDot);
MoveInfo info;
if (t == TAG::COUNT_FILE)
emit subMsgChanged(QDir::toNativeSeparators(src)); // 通知界面当前目录
for(auto file : src_files)
{
if(t == TAG::COUNT_FILE) // 先统计文件总数
{
total++;
} else {
info.rm = rm;
info.src = file.filePath();
info.dst = dst_dir.filePath(file.fileName());
freeSpace.acquire();
task_q.enqueue(info); // 将文件信息放入队列
usedSpace.release();
count++;
//通知界面更新进度
emit subMsgChanged(QString("[%1%] %2/%3").arg(int(100*((float)count/total))).arg(count).arg(total));
}
}
QStringList src_dirs = src_dir.entryList(QStringList{}, QDir::Dirs | QDir::NoDotAndDotDot);
// 递归处理所有子目录
for(auto sd : src_dirs)
{
if(!dst_dir.exists(sd) && t == TAG::HANDLE)
dst_dir.mkdir(sd);
walkPath(src_dir.filePath(sd), dst_dir.filePath(sd), t);
}
}
Producer::~Producer()
{
}
class Consumer : public QThread
{
Q_OBJECT
public:
Consumer(QObject *parent=nullptr);
~Consumer();
void run();
};
Consumer::Consumer(QObject *parent)
: QThread(parent)
{
}
void Consumer::run()
{
MoveInfo info;
qDebug() << currentThreadId();
while (true)
{
usedSpace.acquire();
info = task_q.dequeue(); // 获取一个文件信息
freeSpace.release();
if (info.src.isEmpty()) // 如果文件名为空,则中断,结束
break;
if(!QFileInfo::exists(info.dst))
{
QFile::copy(info.src, info.dst);
qDebug() << "hellow world"; // 不加这一句就会崩溃
}
if(info.rm)
QFile::remove(info.src);
}
}
Consumer::~Consumer()
{
}
void MainWindow::start()
{
mProducer.setParams("D:/files", "D:/target/", false);
mProducer->start();
for (int i = 0; i < 8; i++)
{
Consumer *c = new Consumer();
connect(c, &Consumer::finished, c, &Consumer::deleteLater);
c->start();
}
}