【写在前面】

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

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

关于 QCryptographicHash

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

主要特点:

  1. 支持多种哈希算法:QCryptographicHash 提供了多种哈希算法的支持,允许开发者根据具体需求选择合适的算法。
  2. 简单易用的接口:QCryptographicHash 提供了简单易用的接口来计算哈希值。开发者可以通过调用 QCryptographicHash::hash() 静态方法或创建 QCryptographicHash 对象并使用 addData()result() 方法来计算哈希值。
  3. 逐块计算:`QCryptographicHash 还可以逐块地计算哈希值,这对于处理大文件或流式数据非常有用。
  4. 可重复使用:QCryptographicHash 对象可以多次使用。当计算完一个哈希值后,可以通过调用 reset() 方法重置对象,然后继续计算新的哈希值。

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

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


【正文开始】

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

AsyncHasher 的使用方法非常简单:

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

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

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

  4. 通过 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

【结语】

最后:项目链接(多多star呀.._):

Github 地址:https://github.com/mengps/QmlControls/tree/master/AsyncHasher

Qt 中实现异步散列器的更多相关文章

  1. 基于Qt Phonon模块实现音乐播放器

    这次使用Qt实现的是一个本地音乐播放器,可以播放下载在计算机本地的音乐,提供了添加歌曲,歌曲列表,清空列表的功能.默认歌曲列表循环播放.音乐播放的实现主要依赖的是Qt 的多媒体框架phonon.该音乐 ...

  2. Shiro入门学习之散列算法与凭证配置(六)

    一.散列算法概述 散列算法一般用于生成数据的摘要信息,是一种不可逆的算法,一般适合存储密码之类的数据,常见的散列算法如MD5.SHA等,一般进行散列时最好提供一个salt(“盐”),什么意思?举个栗子 ...

  3. 散列(C++实现)

    散列的构成:散列函数,散列表的存储方式,散列表的冲突解决方法. 1.散列函数 较常用的散列函数有除留余数法,数字分析法,平方取中法,折叠法. 2.散列表的存储方式 闭散列法(开地址法),用数组存储:开 ...

  4. 数据结构与算法分析java——散列

    1. 散列的概念 散列方法的主要思想是根据结点的关键码值来确定其存储地址:以关键码值K为自变量,通过一定的函数关系h(K)(称为散列函数),计算出对应的函数值来,把这个值解释为结点的存储地址,将结点存 ...

  5. asyncio之异步上下文管理器

    异步上下文管理器 前面文章我们提到了上下文管理器,但是这个上下文管理器只适用于同步代码,不能用于异步代码(async def形式),不过不用担心今天我们就来讨论在异步中如何使用上下文管理器. 特别提醒 ...

  6. 【数据结构与算法Python版学习笔记】查找与排序——散列、散列函数、区块链

    散列 Hasing 前言 如果数据项之间是按照大小排好序的话,就可以利用二分查找来降低算法复杂度. 现在我们进一步来构造一个新的数据结构, 能使得查找算法的复杂度降到O(1), 这种概念称为" ...

  7. Windows系统散列值获取分析与防范

    LM Hash && NTLM Hash Windows操作系统通常使用两种方法对用户的明文进行加密处理,在域环境中,用户信息存储在ntds.dit中,加密后为散列值.Windows操 ...

  8. Javascript中的字典和散列

    function Dictionary() { var items={}; this.set=function (key,value) { items[key]=value; }; this.remo ...

  9. Django 用散列隐藏数据库中主键ID

    最近看到了一篇讲Django性能测试和优化的文章, 文中除了提到了很多有用的优化方法, 演示程序的数据库模型写法我觉得也很值得参考, 在这单独记录下. 原文的演示代码有些问题, 我改进了下, 这里可以 ...

  10. shiro中自定义realm实现md5散列算法加密的模拟

    shiro中自定义realm实现md5散列算法加密的模拟.首先:我这里是做了一下shiro 自定义realm散列模拟,并没有真正链接数据库,因为那样东西就更多了,相信学到shiro的人对连接数据库的一 ...

随机推荐

  1. Mybatis 插入后获取主键

    项目结构 数据表结构 pom.xml <?xml version="1.0" encoding="UTF-8"?> <project xmln ...

  2. 第八节 JMeter基础-高级登录【数据库数据驱动】

    声明:本文所记录的仅本次操作学习到的知识点,其中商城IP错误,请自行更改. 背景:获取数据库用户表中的数据进行登录接口测试.思路: 引用jar包[测试计划]. 设置数据库的连接信息,取变量名db1-- ...

  3. MiniAuth 一个轻量 ASP.NET Core Identity Web 后台管理中间插件

    MiniAuth 一个轻量 ASP.NET Core Identity Web 后台管理中间插件 「一行代码」为「新.旧项目」 添加 Identity 系统跟用户.权限管理网页后台系统 开箱即用,避免 ...

  4. 题解:P10320 勇气(Courage)

    P10320 勇气(Courage) 推导过程 本题是一道数学题,重点是如何推导出正确式子. 首先,先特判几个特殊点: 当 \(n>=2\) 且 \(x=2\) 时,是不存在解的,战斗力无论何时 ...

  5. Windows版本免费PyMol的安装

    技术背景 在前面一篇博客中,我们介绍过在Linux平台下安装和使用免费版本的PyMol.其实同样的这个免费版在Windows平台上(这里以win11为例)也是支持的. 安装流程 这个免费版本的PyMo ...

  6. LeetCode455.分发饼干

    LeetCode题目链接:https://leetcode.cn/problems/assign-cookies/description/ 题目叙述 假设你是一位很棒的家长,想要给你的孩子们一些小饼干 ...

  7. nginx灰度发布、网站限速和防盗链

    一.灰度发布(金丝雀发布) 灰度发布时使用比较平稳的过渡方式升级或者替换产品项目的方法统称 主要作用 及时发现项目问题 尽早获取用户反馈的信息,以改进产品 如果项目产生问题,可以将问题影响控制到最小范 ...

  8. 【WSDL】01 JAX-WS 入门案例

    去年这个时候工作遇见时暂时总结的笔记: https://www.cnblogs.com/mindzone/p/14777493.html 当时也不是很清楚,直到最近前同事又遇上了这项技术, 除了WSD ...

  9. 【H5】14 表单 其三 原生表单部件

    现在,我们将详细研究不同表单部件的功能,查看了哪些选项可用于收集不同类型的数据.这个指南有些详尽,涵盖了所有可用的原生表单小部件. 预备知识: 计算机基础知识和对于HTML的基本理解. 目标: 要了解 ...

  10. 【Spring-Security】Re11 Oauth2协议 P2 Redis存储 密码模式令牌

    一.Redis配置 需要的依赖 <dependency> <groupId>org.springframework.boot</groupId> <artif ...