利用Python3实现MD5计算和校验

本篇使用运行、编译环境为Python3.7

概述

需求:①计算文件的MD5,并以JSON形式保存。
②读取JSON中保存的文件MD5,与文件MD5比较,列出MD5不符(损坏)的文件、缺失的文件。

工作流程

①计算MD5:列出文件→计算MD5→写入JSON
②校验MD5:列出文件→计算MD5→读取JSON→对照比较→打印结果

主要使用的模块是MD5计算JSON读写列出文件。为保证可读性,前二者我作为外部模块引入。

主函数

主函数运用到的MD5计算模块被定义为domain.get_md5;JSON读写模块为domain.jsonrw。

为保证程序输出直观,引入了颜色模块(Colorama),它不是Python3.7自带的库,需要在cmd中通过pip install colorama安装。(Python3.7貌似自带了pip,如果没有pip麻烦自己下载一下)没有pip玩个榔头的Python

import os
import sys
import colorama
#下面是自己的库
from domain.jsonrw import *
from domain.get_md5 import *

colorama.init(autoreset=True)

def main():
    print("m : MD5校验,对目录下的所有文件计算MD5并保存\nc : CheckMD5,对保存的MD5验证,确保文件完整性。")
    #输入m就转到计算MD5的流程,输入c就对MD5进行校验。
    todo = input("请输入(m/c,默认c):")
    if ((todo == 'c') | (len(todo) == 0)): #用len判断输入是否为空,如果为空就默认执行校验。
        print("开始校验MD5")
        checkmd5()
    elif (todo == 'm'):
        print("开始计算并保存MD5")
        computemd5()
    else:
        main()
    
    def choose():
        print('r:重新选择\nl:退出程序')
        nexttodo=input("请输入(r/l):")
        if (nexttodo == 'l'):
            return 0
        elif(nexttodo == 'r'):
            main()
        else:
            choose()

    choose()


#计算并写入MD5---m
def computemd5(): 
    cdir = r'./'    #查找范围为自身所在的路径
    filelist = list_files(cdir)
    nfile = 0
    dic = {}
    if(filelist==0):
        return 0

    for thefile in filelist:   #遍历list下的所有文件
        nfile = nfile + 1
        print('\033[1;33m ' + '正在计算第' + str(nfile) + '个文件:' + thefile + '的MD5' + ' \033[0m')
        filemd5 = get_file_md5(thefile)#调用上面的函数,计算出MD5值。
        print ('\033[1;32m ' + '第' + str(nfile) + '个文件:' + thefile + ',MD5计算完成:' + filemd5 + ' \033[0m')
        dic[thefile] = filemd5

    dic2json(dic)
    print ('\033[1;32m ' + '全部文件MD5计算完毕,已自动保存为json文件' + ' \033[0m')

def checkmd5():
    cdir = r'./'
    filelist = list_files(cdir)
    json_md5_dic = json2dic()

    if (filelist==0):
        return 0


    nfile = 0
    checkfailed = list()
    if (json_md5_dic == 0):
        print('\033[1;31m ' + '错误:未找到md5.json文件,请检查' +' \033[0m')
        return 0
    for jsonfilename , jsonmd5 in json_md5_dic.items():
        nfile += 1
        print ('正在验证第' + str(nfile) + '个文件:' + jsonfilename)
        filemd5 = get_file_md5(jsonfilename)
        if (filemd5 == jsonmd5):
            print('\033[1;32m ' + '文件' + jsonfilename + '的MD5验证通过:' + jsonmd5 + ' \033[0m')
        else:
            print('\033[1;31m ' + '文件' + jsonfilename + '的MD5校验失败,\n记录值为:' + jsonmd5 + ',实际值为' + filemd5 + ',请检查文件完整性' +' \033[0m')
            checkfailed.append(jsonfilename)
        filelist.remove(jsonfilename)
    print('校验完毕,结果如下:')
    print('MD5异常的文件:')#把校验未通过的文件列出
    for temp in checkfailed:
        print('\033[1;31m ' + temp + '\033[0m')
    print('未记录的文件:')
    for temp in filelist:
        print('\033[1;34m ' + temp + '\033[0m')

#列出目录下的所有文件
def list_files(filedir): 
    _files = []
    for par ,dirn, filen in os.walk(filedir):
        for filename in filen:
            _files.append(os.path.join(par,filename))
    _files.remove('./'+os.path.basename(sys.argv[0]))#获取自己的文件名,把自己移出列表.
    if './md5.json' in _files:
        _files.remove('./md5.json')               #如果存在md5.json文件,则一并排除
    if (len(_files)!=0):
        return _files
    else:
        print('\033[1;31m ' + '错误:路径下未找到需要计算的文件,请检查。程序不会计算自身和md5.json文件的md5' +' \033[0m')
        return 0



main()

模块

MD5计算

需要指定的变量为文件的路径(相对/绝对)

注意点:这是一个可能有几GB大小的二进制文件,不是一个简单的str字符串,我们不可能像计算字符串hash一样,把整个文件赋值给一个变量然后装载到一块内存区域里去,因此我们需要分块来计算。同时MD5是以512位分组迭代计算的,因此理论上我们的分片大小只要保证是512的整数倍就行,我们这里定为4096(512*8)。

import hashlib

#计算md5方法

def get_file_md5(fname):
    md = hashlib.md5()        #一定要先实例化了
    #面向对象
    with open(fname,'rb') as fobj:  #打开文件fname,以rb,即只读二进制方式读取
        while True:
            data = fobj.read(4096)
            if not data:
                break
            md.update(data)#更新对象内容
    return md.hexdigest()  #返回完整对象的MD5

JSON转换

没啥好说的,用到自带的json模块,实现从字典到JSON和从JSON到字典两种功能。

import os
import json


def json2dic():
    if (os.path.exists('md5.json')):   #检查一下有没有保存的json文件
        jsonfile = open('md5.json', 'r')
        jsvalue = jsonfile.read()
        dic = json.loads(jsvalue)    #转换成字典后赋值,return
        return dic
    else:
        print('当前路径下未找到md5.json文件,请检查。')
        return 0

def dic2json(dic):
    jsvalue = json.dumps(dic)     #把字典转换成json
    with open('md5.json', 'w') as json_file:
        json_file.write(jsvalue)

源码&成品

GitHub地址

声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得UP主同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理:DMCA投诉/Report
学习区-技术教程

[安卓]源导入漫画小说app

2022-9-29 8:51:20

学习区-技术教程

NovelAI WEBUI部署从入门到入土(含文件下载)

2022-10-23 19:41:22

6 条回复 A文章作者 M管理员
  1. chiyuuchuu

    我以为是实现MR

  2. dog

    powershell下的MD5校验:
    certutil -hashfile yourfilename.ext MD5
    certutil -hashfile yourfilename.ext SHA1
    certutil -hashfile yourfilename.ext SHA256
    虽然你可能用不到,但是不能没有牌面!

  3. 2441214635

    感谢分享

  4. 2441214635

    谢谢大佬

个人中心
购物车
优惠劵
今日签到
有新私信 私信列表
搜索