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
【结语】
最后:项目链接(多多star呀.._):
Github 地址:https://github.com/mengps/QmlControls/tree/master/AsyncHasher
Qt 中实现异步散列器的更多相关文章
- 基于Qt Phonon模块实现音乐播放器
这次使用Qt实现的是一个本地音乐播放器,可以播放下载在计算机本地的音乐,提供了添加歌曲,歌曲列表,清空列表的功能.默认歌曲列表循环播放.音乐播放的实现主要依赖的是Qt 的多媒体框架phonon.该音乐 ...
- Shiro入门学习之散列算法与凭证配置(六)
一.散列算法概述 散列算法一般用于生成数据的摘要信息,是一种不可逆的算法,一般适合存储密码之类的数据,常见的散列算法如MD5.SHA等,一般进行散列时最好提供一个salt(“盐”),什么意思?举个栗子 ...
- 散列(C++实现)
散列的构成:散列函数,散列表的存储方式,散列表的冲突解决方法. 1.散列函数 较常用的散列函数有除留余数法,数字分析法,平方取中法,折叠法. 2.散列表的存储方式 闭散列法(开地址法),用数组存储:开 ...
- 数据结构与算法分析java——散列
1. 散列的概念 散列方法的主要思想是根据结点的关键码值来确定其存储地址:以关键码值K为自变量,通过一定的函数关系h(K)(称为散列函数),计算出对应的函数值来,把这个值解释为结点的存储地址,将结点存 ...
- asyncio之异步上下文管理器
异步上下文管理器 前面文章我们提到了上下文管理器,但是这个上下文管理器只适用于同步代码,不能用于异步代码(async def形式),不过不用担心今天我们就来讨论在异步中如何使用上下文管理器. 特别提醒 ...
- 【数据结构与算法Python版学习笔记】查找与排序——散列、散列函数、区块链
散列 Hasing 前言 如果数据项之间是按照大小排好序的话,就可以利用二分查找来降低算法复杂度. 现在我们进一步来构造一个新的数据结构, 能使得查找算法的复杂度降到O(1), 这种概念称为" ...
- Windows系统散列值获取分析与防范
LM Hash && NTLM Hash Windows操作系统通常使用两种方法对用户的明文进行加密处理,在域环境中,用户信息存储在ntds.dit中,加密后为散列值.Windows操 ...
- Javascript中的字典和散列
function Dictionary() { var items={}; this.set=function (key,value) { items[key]=value; }; this.remo ...
- Django 用散列隐藏数据库中主键ID
最近看到了一篇讲Django性能测试和优化的文章, 文中除了提到了很多有用的优化方法, 演示程序的数据库模型写法我觉得也很值得参考, 在这单独记录下. 原文的演示代码有些问题, 我改进了下, 这里可以 ...
- shiro中自定义realm实现md5散列算法加密的模拟
shiro中自定义realm实现md5散列算法加密的模拟.首先:我这里是做了一下shiro 自定义realm散列模拟,并没有真正链接数据库,因为那样东西就更多了,相信学到shiro的人对连接数据库的一 ...
随机推荐
- 四 黑马程序员-java面向对象(上)
一.:面向对象 (1)面向对象:是基于面向过程的一种思想. 面向过程:以函数为基础,关注实现过程. 面向对象:以对象为基础,关注实现结果. (2)面向对象的思想特点: A:是一种更符合人们思考习惯的思 ...
- 解决方案 | MiKTex SSL connect error code 35
可能是:你的网络屏蔽了需要连接的网站,更换手机流量热点即可解决
- 面试官:Dubbo一次RPC请求经历哪些环节?
大家好,我是三友~~ 今天继续探秘系列,扒一扒一次RPC请求在Dubbo中经历的核心流程. 本文是基于Dubbo3.x版本进行讲解 一个简单的Demo 这里还是老样子,为了保证文章的完整性和连贯性,方 ...
- [oeasy]python0068_控制序列_清屏_控制输出位置_2J
光标位置 回忆上次内容 上次了解了键盘演化的过程 ESC 从 组合键 到 独立按键 ESC 的目的 是进入控制序列 配置控制信息 控制信息 \033[y;xH 设置光标位置 \033[2J 清屏 这到 ...
- 用IO多路复用实现 nginx 静态资源代理(C/Java/Golang)
用IO多路复用实现 nginx 静态资源代理(C/Java/Golang) 效果展示 代理 HTML 代理图片 注意, 静态资源代理基于 HTTP, 可以了解上一篇文章: 几十行代码使用TCP简单实现 ...
- Jmeter函数助手15-FiletoString
FiletoString函数用于一次读取整个文件值. 输入文件的全路径:填入文件路径 File encoding if not the platform default (opt):读取文件的编码格式 ...
- 关于VS2022无法打开源文件<stdio.h>报错
Q:本人今天下载VS2022,在billibilli观看到不靠谱教程以至于无法输出hello world A:经过网上查询发现 解决方案/侵删 web:https://www.cnblogs.com/ ...
- 【Java】EasyCaptcha 封装验证码接口
依赖坐标: <dependency> <groupId>com.github.whvcse</groupId> <artifactId>easy-cap ...
- 【Dos-BatchPrograming】03
--1.AT 计划任务 Microsoft Windows [版本 10.0.19041.746] (c) 2020 Microsoft Corporation. 保留所有权利. C:\Users\A ...
- 【转载】冲压过程仿真模拟及优化 —— 冲压仿真的方法分类PPT
地址: https://www.renrendoc.com/paper/310415051.html