zdsub 发表于 2023-7-25 11:59

基于QT开发的跨平台文件校验工具

本帖最后由 zdsub 于 2023-8-13 09:42 编辑

# QtFileHash

QtFileHash是一款基于Qt开发的跨平台文件校验工具,支持Windows、Linux、MacOS平台,支持MD4、MD5、SHA1、SHA256、SHA512算法。

项目地址:(https://github.com/zdsub/QtFilehash)
项目演示:(https://www.bilibili.com/video/BV1ZM4y1x7rk)

## 功能特点

1.基于Qt 5.15开发
2.支持Windows、Linux、MacOS平台
3.支持MD4、MD5、SHA1、SHA256、SHA512算法
4.支持计算单个或多个文件
5.支持通过拖拽,计算单个或多个文件
6.支持通过启动参数,计算单个或多个文件
7.支持分块计算和停止计算
8.支持显示计算进度
9.支持复制、导出、清除计算结果

## 项目截图

Windows

!(https://s1.ax1x.com/2023/07/16/pCIEmdA.png)

Linux

!(https://s1.ax1x.com/2023/07/16/pCIEOYt.png)

MacOS

!(https://s1.ax1x.com/2023/07/16/pCI2Imt.jpg)

## 核心代码

filehashthread.h

```
#ifndef FILEHASHTHREAD_H
#define FILEHASHTHREAD_H

#include <QThread>
#include <QCryptographicHash>

class FileHashThread : public QThread
{
    Q_OBJECT

public:
    // 构造函数
    FileHashThread();
    // 析构函数
    ~FileHashThread();

    // 线程函数
    void run() Q_DECL_OVERRIDE;

    // 设置待计算文件集合
    void setFileList(QStringList fileList);
    // 设置是否停止计算
    void setStop(bool isStop);

private:
    // 计算文件哈希
    void hash(QString path, int index);
    // 发送错误信息
    void emitError(int index, QString error);

private:
    // 待计算文件集合
    QStringList fileList;

    // 是否停止计算
    bool isStop;
    // 文件缓冲区
    int bufferSize;

    // 校验算法
    QCryptographicHash* md4;
    QCryptographicHash* md5;
    QCryptographicHash* sha1;
    QCryptographicHash* sha256;
    QCryptographicHash* sha512;

signals:
    // 哈希校验开始
    void hashStarted(int count);
    // 哈希校验结束
    void hashEnded();
    // 哈希校验错误
    void hashError(QString error);
    // 哈希校验进度改变
    void hashProgressChanged(int progress);
    // 哈希校验索引改变
    void hashIndexChanged(int index);
    // 哈希校验结果
    void hashResult(QString result);
};

#endif // FILEHASHTHREAD_H
```

filehashthread.cpp

```
#include "filehashthread.h"

#include <QFile>
#include <QFileInfo>

FileHashThread::FileHashThread()
{
    isStop = false;
    bufferSize = 4096;

    md4 = new QCryptographicHash(QCryptographicHash::Md4);
    md5 = new QCryptographicHash(QCryptographicHash::Md5);
    sha1 = new QCryptographicHash(QCryptographicHash::Sha1);
    sha256 = new QCryptographicHash(QCryptographicHash::Sha256);
    sha512 = new QCryptographicHash(QCryptographicHash::Sha512);
}

FileHashThread::~FileHashThread()
{
    delete md4;
    delete md5;
    delete sha1;
    delete sha256;
    delete sha512;
}

void FileHashThread::setFileList(QStringList fileList)
{
    this->fileList = fileList;
}

void FileHashThread::setStop(bool isStop)
{
    this->isStop = isStop;
}

void FileHashThread::run()
{
    int size = fileList.size();

    if (size > 0)
    {
      emit hashStarted(size);

      for (int i = 0; i < size && !isStop; i++)
            hash(fileList, i);

      emit hashEnded();
    }
}

void FileHashThread::hash(QString filePath, int index) {
    QFileInfo info(filePath);

    if (!info.exists())
    {
      emitError(index, "文件不存在");
      return;
    }
    else if (!info.isFile())
    {
      emitError(index, "不是文件");
      return;
    }

    QFile file(filePath);

    if (!file.open(QIODevice::ReadOnly))
    {
      emitError(index, "打开文件失败");
      return;
    }

    long long size = 0;
    long long fileSize = file.size();

    if (fileSize != 0)
    {
      while (size < fileSize && !isStop)
      {
            QByteArray byteArray = file.read(bufferSize);

            md4->addData(byteArray);
            md5->addData(byteArray);
            sha1->addData(byteArray);
            sha256->addData(byteArray);
            sha512->addData(byteArray);

            size += byteArray.size();
            emit hashProgressChanged(static_cast<double>(size) / fileSize * 100);
      }
    }
    else
      emit hashProgressChanged(100);

    file.close();

    // 完成计算
    if (size == fileSize)
    {
      // 获取校验结果
      QString _md4 = md4->result().toHex().toUpper();
      QString _md5 = md5->result().toHex().toUpper();
      QString _sha1 = sha1->result().toHex().toUpper();
      QString _sha256 = sha256->result().toHex().toUpper();
      QString _sha512 = sha512->result().toHex().toUpper();

      // 格式化校验结果
      QString message = "文件: %1\n"
                        "大小: %2字节\n"
                        "MD4: %3\n"
                        "MD5: %4\n"
                        "SHA1: %5\n"
                        "SHA256: %6\n"
                        "SHA512: %7\n";
      QString result = message.arg(filePath, QString::number(fileSize), _md4, _md5, _sha1, _sha256, _sha512);

      emit hashResult(result);
      emit hashIndexChanged(index + 1);
    }

    // 重置检验结果
    md4->reset();
    md5->reset();
    sha1->reset();
    sha256->reset();
    sha512->reset();
}

void FileHashThread::emitError(int index, QString error)
{
    emit hashError(fileList + "\n" + error + "\n");
    emit hashProgressChanged(100);
    emit hashIndexChanged(index + 1);
}
```

Hmily 发表于 2023-7-25 14:17

一、本版块仅限分享编程技术和源码相关内容,发布帖子必须带上关键代码和具体功能介绍【20220924强制执行】,详见『代码插入规范』。

netpeng 发表于 2023-7-25 16:53

支持原创,感谢分享。

zdsub 发表于 2023-7-26 09:11

Hmily 发表于 2023-7-25 14:17
一、本版块仅限分享编程技术和源码相关内容,发布帖子必须带上关键代码和具体功能介绍【20220924强制执行】 ...

已补上关键代码。

hongyemosuo 发表于 2023-7-26 13:19

有CMake版的项目吗{:1_899:}
页: [1]
查看完整版本: 基于QT开发的跨平台文件校验工具