在C++ Qt中实现异步散列器的代码示例

 更新时间:2024年09月11日 08:29:12   作者:梦起丶  
在很多工作中,我们需要计算数据或者文件的散列值,例如登录或下载文件,而在 Qt 中,负责这项工作的类为 QCryptographicHash,本文给大家介绍了在C++ Qt中实现异步散列器的代码示例,需要的朋友可以参考下

【写在前面】

在很多工作中,我们需要计算数据或者文件的散列值,例如登录或下载文件。

而在 Qt 中,负责这项工作的类为 QCryptographicHash

关于 QCryptographicHash

QCryptographicHash 是 Qt 框架中提供的一个用于生成加密散列(哈希值)的类。该类可以将任意长度的输入(二进制或文本数据)转换成固定长度的输出(哈希值),这一过程是不可逆的。QCryptographicHash 支持多种哈希算法,包括 MD4、MD5、SHA-1、SHA-224、SHA-256、SHA-384 和 SHA-512 等,这些算法在数据完整性校验、密码存储、数字签名等应用场景中非常有用。

主要特点:

支持多种哈希算法:QCryptographicHash 提供了多种哈希算法的支持,允许开发者根据具体需求选择合适的算法。

简单易用的接口:QCryptographicHash 提供了简单易用的接口来计算哈希值。开发者可以通过调用 QCryptographicHash::hash() 静态方法或创建 QCryptographicHash 对象并使用 addData() 和 result() 方法来计算哈希值。

逐块计算:`QCryptographicHash 还可以逐块地计算哈希值,这对于处理大文件或流式数据非常有用。

可重复使用:QCryptographicHash 对象可以多次使用。当计算完一个哈希值后,可以通过调用 reset() 方法重置对象,然后继续计算新的哈希值。

然鹅, 虽然 QCryptographicHash 很优秀,但它最大的问题在于其散列值的计算是同步的( 即阻塞 ),对小数据来说并没什么影响,但对大数据来说则意味明显卡顿。

因此,我将 QCryptographicHash 进行简单封装,扩展了实用性的同时并将计算改为异步,还增加了进度通知和结束通知。

【正文开始】

先来看看 AsyncHasher 的使用效果图:

AsyncHasher 的使用方法非常简单:

  • 包含头文件:在使用 AsyncHasher 之前,需要包含相应的头文件 #include "asynchasher.h"

  • 通过 setSource / setSourceText / setSourceData/ setSourceObject 设置源目标。

  • 通过 void hashProgress(qint64 processed, qint64 total) 来获取进度,void finished() 通知计算结束。

  • 通过 QString hashValue() const 获取最终结果。

例如 C++ 使用:

    AsyncHasher *hasher = new AsyncHasher;
    hasher->setSourceText("Test Text");
    QObject::connect(hasher, &AsyncHasher::finished, [hasher]{
        qDebug() << hasher->hashValue();
    });

并且我还做了 Qml 适配,使用方法:

    AsyncHasher {
        id: textHasher
        algorithm: AsyncHasher.Md5
        onStarted: {
            startTime = Date.now();
        }
        onFinished: {
            totalTime = Date.now() - startTime;
            console.log("HashValue:", hashValue, "time:", totalTime);
        }
        property real startTime: 0
        property real totalTime: 0
    }

完整头文件如下:

#ifndef ASYNCHASHER_H
#define ASYNCHASHER_H

#include <QCryptographicHash>
#include <QFuture>
#include <QObject>
#include <QUrl>

QT_FORWARD_DECLARE_CLASS(QNetworkAccessManager);

QT_FORWARD_DECLARE_CLASS(AsyncHasherPrivate);

class AsyncHasher : public QObject
{
    Q_OBJECT

    Q_PROPERTY(QCryptographicHash::Algorithm algorithm READ algorithm WRITE setAlgorithm NOTIFY algorithmChanged)
    Q_PROPERTY(bool asynchronous READ asynchronous WRITE setAsynchronous NOTIFY asynchronousChanged)
    Q_PROPERTY(QString hashValue READ hashValue NOTIFY hashValueChanged)
    Q_PROPERTY(int hashLength READ hashLength NOTIFY hashLengthChanged)
    Q_PROPERTY(QUrl source READ source WRITE setSource NOTIFY sourceChanged)
    Q_PROPERTY(QString sourceText READ sourceText WRITE setSourceText NOTIFY sourceTextChanged)
    Q_PROPERTY(QByteArray sourceData READ sourceData WRITE setSourceData NOTIFY sourceDataChanged)
    Q_PROPERTY(QObject* sourceObject READ sourceObject WRITE setSourceObject NOTIFY sourceObjectChanged)

public:
    Q_ENUMS(QCryptographicHash::Algorithm);

    explicit AsyncHasher(QObject *parent = nullptr);
    ~AsyncHasher();

    QNetworkAccessManager *networkManager() const;

    QCryptographicHash::Algorithm algorithm();
    void setAlgorithm(QCryptographicHash::Algorithm algorithm);

    bool asynchronous() const;
    void setAsynchronous(bool async);

    QString hashValue() const;

    int hashLength() const;

    QUrl source() const;
    void setSource(const QUrl &source);

    QString sourceText() const;
    void setSourceText(const QString &sourceText);

    QByteArray sourceData() const;
    void setSourceData(const QByteArray &sourceData);

    QObject *sourceObject() const;
    void setSourceObject(QObject *sourceObject);

    bool operator==(const AsyncHasher &hasher);
    bool operator!=(const AsyncHasher &hasher);

    QFuture<QByteArray> static hash(const QByteArray &data, QCryptographicHash::Algorithm algorithm);

signals:
    void algorithmChanged();
    void asynchronousChanged();
    void hashValueChanged();
    void hashLengthChanged();
    void sourceChanged();
    void sourceTextChanged();
    void sourceDataChanged();
    void sourceObjectChanged();
    void hashProgress(qint64 processed, qint64 total);
    void started();
    void finished();

private slots:
    void setHashValue(const QString &value);

private:
    Q_DECLARE_PRIVATE(AsyncHasher);
    QScopedPointer<AsyncHasherPrivate> d_ptr;
};

#endif // ASYNCHASHER_H

【结语】

以上就是在C++ Qt中实现异步散列器的代码示例的详细内容,更多关于C++ Qt异步散列器的资料请关注脚本之家其它相关文章!

相关文章

  • C++数据精度问题(对浮点数保存指定位小数)

    C++数据精度问题(对浮点数保存指定位小数)

    这篇文章主要介绍了对浮点数保存指定位小数。比如, 1.123456. 要保存1位小数,,调用方法后, 保存的结果为: 1.1。 再比如,1.98765, 保存2位小数的结果为: 2.00,需要的朋友可以参考下
    2017-08-08
  • C++实现的打字母游戏示例

    C++实现的打字母游戏示例

    这篇文章主要介绍了C++实现的打字母游戏,涉及C++字体操作、时间及键盘响应相关操作技巧,需要的朋友可以参考下
    2017-08-08
  • C语言实现飞机售票系统

    C语言实现飞机售票系统

    这篇文章主要为大家详细介绍了C语言实现飞机售票系统,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-05-05
  • C与C++中结构体的区别

    C与C++中结构体的区别

    C中的结构体只涉及到数据结构,而不涉及到算法,也就是说在C中数据结构和算法是分离的,而到C++中一类或者一个结构体可以包含函数(这个函数在C++我们通常中称为成员函数),C++中的结构体和类体现了数据结构和算法的结合
    2013-10-10
  • C语言单链队列的表示与实现实例详解

    C语言单链队列的表示与实现实例详解

    这篇文章主要介绍了C语言单链队列的表示与实现,对于研究数据结构与算法的朋友来说很有参考借鉴价值,需要的朋友可以参考下
    2014-07-07
  • Qt中QByteArray​类型的使用详解

    Qt中QByteArray​类型的使用详解

    QByteArray是Qt中处理原始字节数据和8位字符串的核心容器类,本文就来详解的介绍一下QByteArray​类型的使用,感兴趣的可以了解一下
    2025-12-12
  • 详谈C++ socket网络编程实例(2)

    详谈C++ socket网络编程实例(2)

    这篇文章主要为大家介绍了C++ socket网络编程实例,具有一定的参考价值,感兴趣的小伙伴们可以参考一下,希望能够给你带来帮助
    2021-11-11
  • C语言中无符号数和有符号数之间的运算

    C语言中无符号数和有符号数之间的运算

    C语言中有符号数和无符号数进行运算默认会将有符号数看成无符号数进行运算,其中算术运算默认返回无符号数,逻辑运算当然是返回0或1了。下面通过一个例子给大家分享C语言中无符号数和有符号数之间的运算,一起看看吧
    2017-09-09
  • 使用DeepSeek API 结合VSCode提升开发效率

    使用DeepSeek API 结合VSCode提升开发效率

    这篇文章主要介绍了DeepSeek API与Visual Studio Code (VSCode)结合使用,以提升软件开发效率,具有一定的参考价值,感兴趣的可以了解一下
    2025-01-01
  • 关于C语言中的指针与二维数组

    关于C语言中的指针与二维数组

    这篇文章主要介绍了关于C语言中的指针与二维数组,C语言中,指针是一个复杂但又灵活多变的知识点,我们知道,在一维数组中,对于一个数组a[],*a,a,&a,都表示a的首地址,但如果与二维数组混合使用,就显得更为复杂了,需要的朋友可以参考下
    2023-07-07

最新评论