Qt小案例(二)重复文件检测

发布于:2023-01-31 ⋅ 阅读:(552) ⋅ 点赞:(0)

目录

一、前言

二、基础知识介绍

1.读取文件内容和识别文件MD5

2.获取文件夹下所有文件路径

3.信号与槽的使用

4.多线程的使用

5.封装

三、代码部分

四、结果


一、前言

本案例涉及读取文件内容,识别文件MD5,获取文件夹下所有文件路径,信号与槽的使用、多线程的使用以及封装的简单应用,具有较高学习借鉴意义。

重复文件检测Qt源码

基于Qt开发的重复文件检测小程序


二、基础知识介绍

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.多线程的使用

  1. 头文件中创建QThread对象
  2. 构造函数中启用:
    对象名.start():
  3. 析构函数中退出:
    对象名.exit():
  4. 析构函数中还有使它等待一会
    对象名.wait(10*1000)://10s
    
  5. 如果线程里面的数据类型是自设的需要注册一下
    qRegisterMetaType<QHash<QByteArray,QStringList>>("QHash<QByteArray,QStringList>");//注册<QHash<QByteArray,QStringList>

5.封装

  1. 创建一个函数类来实现封装
  2. 提高信号与槽实现连接

三、代码部分

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 &currentText);

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 &currentText)
{
    ui->listWidget_2->clear();
    QByteArray md=currentText.toLocal8Bit();
    QStringList text=this->pt[md];
    ui->listWidget_2->addItems(text);
}

四、结果

本文含有隐藏内容,请 开通VIP 后查看

网站公告

今日签到

点亮在社区的每一天
去签到