目录
一、概述
本工具居于hashlib+PyQt+QFileDialog写的小工具,主要是为了简单的获取相关文件或者一些数据的哈希值数据。
1.1 版本信息:
以下为使用到的相关类库的版本信息
- PyQt5 5.14.0
- PyQt5-sip 12.12.2
- pyqt5-tools 5.14.0.1.7
- Python 3.8.6
当前小工具的版本信息如下: - V1.0.0.0
1.2 基本信息:
1.2.1 软件支持的内容:
以下为当前小工具支持获取哈希值的文件类型及文本信息:
- 普通文本文件:.txt、.docs、.doc、.xml等
- 图片文件:.png、.gif等
- 压缩包文件:.zip等
- 应用程序:.exe、.msi
- 直接文本框输入文本
- 其他的未进一步验证
注: 打开文件时,数据的文本框中显示的是文件的完整路径,而非具体数据内容。
1.2.2 支持的编码格式
以下为当前版本小工具支持的编码格式:
- MD5
- SHA1
- SHA256
实际子项编程时,可以根据自己的需要添加更多的编码格式,具体可以参考hashlib类库的使用 。
Python学习笔记-使用哈希算法Hash,Hashlib进行数据加密
1.3 软件界面图
软件界面如上图,基本功能说明如下:
- 通过上方单选按钮选择不同的编码方式;
- 通过“打开文件”可以选择想要获取hash值的文件,此时只是获取文件路径,并显示在数据中;
- 亦可以根据自己需要将具体的文本数据直接输入到数据文本框中;
- 点击“计算”按钮,软件会自动识别是否为文件,或者文本内容,进行Hash值计算,并显示在下方;
- 点击“清除数据”按钮,可以快速的清除数据以及计算出来的Hash值。
注意: 若是输入文本进行计算时,为了避免空格无法观测,造成的信息错误,会默认将首尾的空格删掉。
二、代码实现
代码采用MVC架构模式设计,便于代码的分离解耦,也进一步多练习练习MCV模式的设计。
2.1 View
View是界面,用于与用户进行交互。
使用PyQt进行界面开发,主界面继承于QMainWindow类,通过QGridLayout和QHBoxLayout进行布局。
# _*_ coding:utf-8 _*_
from PyQt5.QtWidgets import QMainWindow
from PyQt5.QtWidgets import QWidget
from PyQt5.QtWidgets import QPushButton
from PyQt5.QtWidgets import QTextEdit
from PyQt5.QtWidgets import QLineEdit
from PyQt5.QtWidgets import QLabel
from PyQt5.QtWidgets import QGridLayout
from PyQt5.QtWidgets import QHBoxLayout
from PyQt5.QtWidgets import QRadioButton
from PyQt5.QtCore import Qt
from PyQt5.QtGui import QIcon
class MainWindow(QMainWindow):
"Main Window"
def __init__(self) -> None:
"""Init"""
super().__init__()
self.init_ui()
def init_ui(self):
"""Init Ui"""
self.setMinimumSize(400,300)
self.resize(400,300)
self.setWindowTitle("Hash Code V1.0.0.0")
self.setWindowIcon(QIcon("res\Gear 2.ico"))
self.central_widget = QWidget()
""" main widget """
self.setCentralWidget(self.central_widget)
self.layout_main = QGridLayout()
self.central_widget.setLayout(self.layout_main)
# Hash type buttong.
self.layout_hashtype = QHBoxLayout()
self.layout_main.addLayout(self.layout_hashtype, 0, 0, Qt.AlignmentFlag.AlignTop)
self.radio_md5 = QRadioButton("MD5")
self.radio_md5.setChecked(True)
self.layout_hashtype.addWidget(self.radio_md5)
self.radio_sha1 = QRadioButton("SHA1")
self.layout_hashtype.addWidget(self.radio_sha1)
self.radio_sha256 = QRadioButton("SHA256")
self.layout_hashtype.addWidget(self.radio_sha256)
self.layout_hashtype.addStretch(1)
self.btn_openfile = QPushButton("打开文件")
self.layout_hashtype.addWidget(self.btn_openfile,alignment=Qt.AlignmentFlag.AlignRight)
# Data
self.layout_main.addWidget(QLabel("数据:"), 1, 0, Qt.AlignmentFlag.AlignLeft)
self.txt_data = QTextEdit()
self.txt_data.setToolTip("""打开文件时则获取文件的Hash值,非文件时直接获取文本框中文本的Hash值!\r\n默认清除首尾空格!""")
self.layout_main.addWidget(self.txt_data, 2, 0)
self.txt_data.setMinimumHeight(50)
# Hash
self.layout_value = QHBoxLayout()
self.layout_main.addLayout(self.layout_value, 3, 0)
self.layout_value.addWidget(QLabel("Hash值:"))
self.layout_value.addStretch(1)
self.btn_clear = QPushButton("清除数据")
self.layout_value.addWidget(self.btn_clear, alignment=Qt.AlignmentFlag.AlignRight)
self.btn_calc = QPushButton("计算")
self.layout_value.addWidget(self.btn_calc, alignment=Qt.AlignmentFlag.AlignRight)
self.txt_value = QTextEdit()
self.layout_main.addWidget(self.txt_value, 4, 0)
2.2 Controller
Controller是界面与模块只见的中间层,用于链接双方。
以继承的方式,直接继承界面,然后进行逻辑编写。
另外一种方式是,界面集成QObject,然后初始化的时候创建一个View类。
# _*_ coding:utf-8 _*_
import os
import hashlib
from PyQt5.QtWidgets import QFileDialog
from PyQt5.QtWidgets import QWidget
from PyQt5.QtWidgets import QPushButton
from PyQt5.QtWidgets import QTextEdit
from PyQt5.QtWidgets import QLineEdit
from PyQt5.QtWidgets import QLabel
from PyQt5.QtWidgets import QGridLayout
from PyQt5.QtWidgets import QHBoxLayout
from PyQt5.QtWidgets import QRadioButton
from view.main_view import MainWindow
class MainWindowController(MainWindow):
"""The controller of mainwindow"""
def __init__(self) -> None:
"""Init"""
super().__init__()
self.btn_openfile.clicked.connect(self.openfile)
self.btn_clear.clicked.connect(self.clear)
self.btn_calc.clicked.connect(self.gethash)
self.show()
def openfile(self):
"""Open File"""
# 打开文件
filepath, filetypelist = QFileDialog.getOpenFileName()
self.txt_data.setText(filepath)
def gethash(self):
"""Get Hash Value"""
# 判断是否未文件,为文件时读取文件进行校验
data = self.txt_data.toPlainText().strip()
try:
if os.path.exists(data):
file = open(data, "rb")
data_b = file.read()
else:
data_b = data.encode("utf-8")
except Exception as err:
self.txt_value.setText(err)
# 计算哈希值,根据不同选项选择不同的算法。
if self.radio_md5.isChecked():
hash_value = hashlib.md5(data_b).hexdigest()
elif self.radio_sha1.isChecked():
hash_value = hashlib.sha1(data_b).hexdigest()
elif self.radio_sha256.isChecked():
hash_value = hashlib.sha256(data_b).hexdigest()
else:
return
# 显示哈希值
self.txt_value.setText(str(hash_value).upper())
def clear(self):
"""Get Hash Value"""
self.txt_value.clear()
self.txt_data.clear()
2.3 Model
小工具,没有model。
三、测试示例
示例1:直接输入文本,然后计算该文本的MD5值。
示例2:打开一个.exe应用程序文件,然后计算该文件的MD5值。