目录
一、前言
本案例涉及读取文件内容,识别文件MD5,获取文件夹下所有文件路径,信号与槽的使用、多线程的使用以及封装的简单应用,具有较高学习借鉴意义。
二、基础知识介绍
1.读取文件内容和识别文件MD5
具体内容可看:Qt小案例(一)获取文本内容和单文件MD5
2.获取文件夹下所有文件路径
采用递归函数重复获取文件路径
QStringList FileMd5::getfile(const QString &path)
{
QStringList ret;
QDir dir(path);
QFileInfoList infolist=dir.entryInfoList(QDir::Files | QDir::Dirs |QDir::NoDotAndDotDot);
for(int i=0;i<infolist.count();++i)
{
QFileInfo fileinfo=infolist.at(i);
if(fileinfo.isDir())
{
QString subDir=fileinfo.absoluteFilePath();
QStringList content=getfile(subDir);
ret.append(content);
}
else
{
QString fileName=fileinfo.absoluteFilePath();
ret.append(fileName);
}
}
return ret;
}
3.信号与槽的使用
//方法1:
QObject::connect(const QObject *sender,const char *signal,const Qobject *receiver,const char *method,Qt::ConnectionType type = Qt::AutoConnection)
//方法2:
connect(信号的发送者,SIGNAL(信号),信号接受者,SLOT(槽函数) );
可参考在里面的介绍:ROS下基于Qt的人机交互开发(二)Qt基础
4.多线程的使用
- 头文件中创建QThread对象
- 构造函数中启用:
对象名.start():
- 析构函数中退出:
对象名.exit():
- 析构函数中还有使它等待一会
对象名.wait(10*1000)://10s
- 如果线程里面的数据类型是自设的需要注册一下
qRegisterMetaType<QHash<QByteArray,QStringList>>("QHash<QByteArray,QStringList>");//注册<QHash<QByteArray,QStringList>
5.封装
- 创建一个函数类来实现封装
- 提高信号与槽实现连接
三、代码部分
1.封装内容FileMd5
FileMd5.h
#ifndef FILEMD5_H
#define FILEMD5_H
#include <QObject>
#include<QByteArray>
#include<QCryptographicHash>
#include<QFile>
#include<QFileInfo>
#include<QDir>
#include<QHash>
class FileMd5 : public QObject
{
Q_OBJECT
public:
explicit FileMd5(QObject *parent = nullptr);
QHash<QByteArray,QStringList> filemd5;
signals:
void getDumplate(const QHash<QByteArray,QStringList>&p);
void progress(int current,int total);
public slots:
void checkDumplate(const QString &path);
protected:
QStringList getfile(const QString &path);
QByteArray getmd5(const QString &path);
};
#endif // FILEMD5_H
FileMd5.cpp
#include "FileMd5.h"
FileMd5::FileMd5(QObject *parent) : QObject(parent)
{
}
//检测重复文件
void FileMd5::checkDumplate(const QString &path)
{
filemd5.clear();
QStringList filepath=getfile(path);
for(int i=0;i<filepath.count();++i)
{
QString context=filepath.at(i);
QByteArray md5=getmd5(context);
filemd5[md5].append(context);
emit progress(i+1,filepath.count());
}
emit getDumplate(filemd5);
}
//获取文件路径
QStringList FileMd5::getfile(const QString &path)
{
QStringList ret;
QDir dir(path);
QFileInfoList infolist=dir.entryInfoList(QDir::Files | QDir::Dirs |QDir::NoDotAndDotDot);
for(int i=0;i<infolist.count();++i)
{
QFileInfo fileinfo=infolist.at(i);
if(fileinfo.isDir())
{
QString subDir=fileinfo.absoluteFilePath();
QStringList content=getfile(subDir);
ret.append(content);
}
else
{
QString fileName=fileinfo.absoluteFilePath();
ret.append(fileName);
}
}
return ret;
}
//获取文件MD5
QByteArray FileMd5::getmd5(const QString &path)
{
QFile file(path);
if(file.open(QIODevice::ReadOnly))
{
QByteArray content=file.readAll();
QByteArray md5=QCryptographicHash::hash(content,QCryptographicHash::Md5);
file.close();
return md5;
}
return QByteArray();
}
2.widget.h
#ifndef WIDGET_H
#define WIDGET_H
#include <QWidget>
#include "FileMd5.h"
#include<QString>
#include<QDir>
#include<QPushButton>
#include<QThread>
#include<QFileDialog>
namespace Ui {
class Widget;
}
class Widget : public QWidget
{
Q_OBJECT
public:
explicit Widget(QWidget *parent = 0);
~Widget();
FileMd5 md5;//创建FileMd5对象,用于连接FileMd5类
QThread thread;//创建线程对象
QHash<QString,QStringList> pt;
signals:
void oncheckDumplate(const QString &path);//用于传入地址,获取文件目录
private slots:
void on_pushButton_clicked();
void ongetDumplate(const QHash<QByteArray,QStringList> &p);
void onprogress(int current,int total);
void on_pushButton_2_clicked();
void on_listWidget_currentTextChanged(const QString ¤tText);
private:
Ui::Widget *ui;
};
#endif // WIDGET_H
3.widget.cpp
#include "widget.h"
#include "ui_widget.h"
#include<QDebug>
Widget::Widget(QWidget *parent) :
QWidget(parent),
ui(new Ui::Widget)
{
ui->setupUi(this);
thread.start();//线程thread开始
md5.moveToThread(&thread);//将md5加入线程thread中
qRegisterMetaType<QHash<QByteArray,QStringList>>("QHash<QByteArray,QStringList>");//注册<QHash<QByteArray,QStringList>
//连接信号与槽
connect(&md5,SIGNAL(getDumplate(QHash<QByteArray,QStringList>)),this,SLOT(ongetDumplate(QHash<QByteArray,QStringList>)));
connect(this,SIGNAL(oncheckDumplate(QString)),&md5,SLOT(checkDumplate(QString)));
connect(&md5,SIGNAL(progress(int,int)),this,SLOT(onprogress(int,int)));
}
Widget::~Widget()
{
thread.exit();//线程thread退出
thread.wait(10*1000);//线程thread等待10s
delete ui;
}
void Widget::on_pushButton_clicked()
{
ui->progressBar->setValue(0);
ui->listWidget->clear();
ui->listWidget_2->clear();
QString text=ui->path->text();
text=QDir::toNativeSeparators(text);//自动将"、”转换成“/”
emit oncheckDumplate(text);//触发oncheckDumplate信号,并将text传入
}
void Widget::ongetDumplate(const QHash<QByteArray, QStringList>&p)
{
for(QHash<QByteArray,QStringList>::const_iterator itr=p.begin();itr!=p.end();++itr)
{
this->pt[itr.key().toHex()].append(itr.value());
if(itr.value().count()>1)
{
ui->listWidget->addItem(itr.key().toHex());
}
}
}
void Widget::onprogress(int current, int total)
{
ui->progressBar->setMaximum(total);
ui->progressBar->setValue(current);
}
void Widget::on_pushButton_2_clicked()
{
QString path=QFileDialog::getExistingDirectory(this,"获取路径",".");
ui->path->setText(path);
}
void Widget::on_listWidget_currentTextChanged(const QString ¤tText)
{
ui->listWidget_2->clear();
QByteArray md=currentText.toLocal8Bit();
QStringList text=this->pt[md];
ui->listWidget_2->addItems(text);
}