HashAlgorithm类支持数据块的Hash运算:对数据前面块通过TransformBlock方法计算,最后一块通过TransformFinalBlock方法计算,结果通过Hash属性获得,便可完成整个Hash过程。对于一个数据流(如文件流),可以利用这个办法,提供Hash的计算进度。下面是一个不带计算进度的使用的使用TransformBlock方式的代码。

using System;
using System.IO;
using System.Security.Cryptography;namespace SHA1_and_MD5
{public static class Algorithm{/// <summary>/// 计算文件的Hash值/// </summary>/// <param name="fileName">文件名</param>/// <param name="hashName">Hash名</param>/// <returns>Hash的文本结果</returns>public static string ComputeHash(string fileName, string hashName){var fs = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.Read);var value = Hash(fs, hashName);fs.Close();return BitConverter.ToString(value).Replace("-", "").ToLower();}/// <summary>/// 计算流的Hash值/// </summary>/// <param name="stream">流</param>/// <param name="hashName">Hash名</param>/// <returns>Hash结果</returns>public static byte[] ComputeHash(Stream stream, string hashName){const int bufferSize = 4096; //0x1000var hash = HashAlgorithm.Create(hashName);int num;var buffer = new byte[bufferSize];do{num = stream.Read(buffer, 0, bufferSize);if (num == bufferSize){hash.TransformBlock(buffer, 0, num, buffer, 0);}else if (stream.Length == stream.Position){hash.TransformFinalBlock(buffer, 0, num);}else if (num > 0){//当 0 < num < bufferSize 的情况var buffer2 = new byte[num];Buffer.BlockCopy(buffer, 0, buffer2, 0, num);hash.TransformBlock(buffer2, 0, num, buffer2, 0);}} while (num > 0);return hash.Hash;}}
}

代码中hashName参数可以为以下值:

hashName参考:http://msdn.microsoft.com/zh-cn/library/wet69s13(VS.90).aspx
   
简单名称 算法实现
SHA SHA1CryptoServiceProvider
SHA1 SHA1CryptoServiceProvider
System.Security.Cryptography.SHA1 SHA1CryptoServiceProvider
System.Security.Cryptography.HashAlgorithm SHA1CryptoServiceProvider
MD5 MD5CryptoServiceProvider
System.Security.Cryptography.MD5 MD5CryptoServiceProvider
SHA256 SHA256Managed
SHA-256 SHA256Managed
System.Security.Cryptography.SHA256 SHA256Managed
SHA384 SHA384Managed
SHA-384 SHA384Managed
System.Security.Cryptography.SHA384 SHA384Managed
SHA512 SHA512Managed
SHA-512 SHA512Managed
System.Security.Cryptography.SHA512 SHA512Managed
   

比如,想计算系统记事本的sha1和md5,可以这样调用:

MessageBox.Show(Algorithm.ComputeHash(@"c:/windows/notepad.exe", "SHA1") + Environment.NewLine +Algorithm.ComputeHash(@"c:/windows/notepad.exe", "MD5"));

接下来,对上面的代码进行修改,加入计算时回调HashingCallback和结束时回调EndCallback,在进行ComputeHash计算时,do-while中每处理完成一组数据,执行一次HashingCallback的回调函数,全部计算完成后执行EndCallback的回调函数。为了在计算过程中取消计算,增加Stop方法,它将_cancel字段设置为true,而ComputeHash方法的do-while条件增加对_cancel的判断。回调函数的参数都包含了一个可传递的object类型的State属性,HashingCallback委托的HashingState参数,目的给出计算Hash的进度,EndCallback的EndState属性,目的通知计算结束,给出是否为中途取消而结束的。而最后的Hash结果通过Hash属性获得。另外,重载ToString方法,直接输出字符串的Hash结果。

于是,我们的代码改写成可实例化的类:

using System;
using System.IO;
using System.Security.Cryptography;namespace SHA1_and_MD5
{public class MyHashAlgorithm{#region Delegates/// <summary>/// 完成Hash计算的回调/// </summary>public delegate void EndCallback(EndState endState);/// <summary>/// 进行Hash计算时的回调/// </summary>public delegate void HashingCallback(HashingState hashingState);#endregionprivate bool _cancel; //取消计算/// <summary>/// 获得Hash结果/// </summary>public byte[] Hash { get; private set; }/// <summary>/// 输出Hash结果的字符串版本/// </summary>/// <returns></returns>public override string ToString(){return Hash != null ? BitConverter.ToString(Hash).Replace("-", "").ToLower() : "";}/// <summary>/// 停止计算/// </summary>public void Stop(){_cancel = true;}/// <summary>/// 计算文件的Hash值/// </summary>/// <param name="fileName">文件名</param>/// <param name="hashName">Hash名</param>/// <param name="hashingCallback">进度回调函数</param>/// <param name="endCallback">结束计算的回调函数</param>/// <param name="state">传递给回调的参数</param>public void ComputeHash(string fileName, string hashName, HashingCallback hashingCallback,EndCallback endCallback, object state){using(var fs = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.Read)){ComputeHash(fs, hashName, hashingCallback, endCallback, state);}}/// <summary>/// 计算流的Hash值/// </summary>/// <param name="stream">流</param>/// <param name="hashName">Hash名</param>/// <param name="hashingCallback">进度回调函数</param>/// <param name="endCallback">结束计算的回调函数</param>/// <param name="state">传递给回调的参数</param>public void ComputeHash(Stream stream, string hashName, HashingCallback hashingCallback, EndCallback endCallback,object state){const int bufferSize = 4096; //0x1000Hash = null;_cancel = false;bool nullHashingCallback = hashingCallback == null; //未指定计算时的回调long bytesRead = 0L; //已经完成的数据long totalBytesLength = stream.Length;HashAlgorithm hash = HashAlgorithm.Create(hashName);int num;var buffer = new byte[bufferSize];do{num = stream.Read(buffer, 0, bufferSize);if (num == bufferSize){hash.TransformBlock(buffer, 0, num, buffer, 0);}else if (totalBytesLength == stream.Position){hash.TransformFinalBlock(buffer, 0, num);}else if (num > 0){var buffer2 = new byte[num];Buffer.BlockCopy(buffer, 0, buffer2, 0, num);hash.TransformBlock(buffer2, 0, num, buffer2, 0);}if (num <= 0 || nullHashingCallback) continue;bytesRead += num;hashingCallback(new HashingState(bytesRead, totalBytesLength, state)); //执行计算时回调} while (num > 0 && !_cancel);Hash = _cancel ? new byte[0] : hash.Hash; //获得计算结果if (endCallback != null) endCallback(new EndState(_cancel, state)); //执行结束回调}#region Nested type: EndState/// <summary>/// 为EndCallback提供数据/// </summary>public class EndState{internal EndState(bool isCancel, object state){IsCancel = isCancel;State = state;}/// <summary>/// 是否取消退出的/// </summary>public bool IsCancel { get; private set; }/// <summary>/// 获得传递的参数/// </summary>public object State { get; private set; }}#endregion#region Nested type: HashingState/// <summary>/// 为HashingCallback提供数据/// </summary>public class HashingState{internal HashingState(long byteRead, long totalBytesLength, object state){BytesRead = byteRead;TotalBytesLength = totalBytesLength;State = state;}/// <summary>/// 获得已经计算完成的字节数/// </summary>public long BytesRead { get; private set; }/// <summary>/// 获得总字节数/// </summary>public long TotalBytesLength { get; private set; }/// <summary>/// 获得传递的参数/// </summary>public object State { get; private set; }}#endregion}
}

为了实现多线程支持,在调用时请使用Thread类实现。

var t =new Thread(() =>hasher.ComputeHash(@"D:/useful/ISO/VS2008SP1CHSX1512981.iso", "SHA1",hashingState => UpdateProgress(hashingState.BytesRead, hashingState.TotalBytesLength),endState => Finish(endState.IsCancel), null)){Name = "ComputeHash",IsBackground = true}; t.Start();

--

感谢uking09检查代码中的BUG。

计算文件Hash(SHA1、MD5等)相关推荐

  1. md5sum 命令 – 计算文件内容的 md5 值

    md5sum 命令的功能是用于计算文件内容的 md5 值,进而比较两个文件相同与否.md5 值是一个128位的二进制数据,转换成16进制则是32位. 用户可以通过此命令对文件内容进行汇总并计算出一个 ...

  2. js快速计算文件hash值

    1. 通过 requestIdleCallback or spark-md5利用浏览器空闲时间切片计算文件hash值: requestIdleCallback简介: window.requestIdl ...

  3. JavaScript计算文件Hash值(sha1 sha 256 md5)

    一.引入外部库CryptoJS(简单) 1.字符串Hash <!DOCTYPE html> <html> <head><title>Hash算法< ...

  4. html5计算文件hash,spark-md5生成hash码,spark-md5计算大文件hash码实现断点续传

    spark-md5import SparkMD5 from 'spark-md5'; var hexHash = SparkMD5.hash('Hi there');        // hex ha ...

  5. vue 计算文件hash值_vue项目打包文件增加hash值

    vue项目打包文件增加hash值 vue-cli2项目 修改vue项目根目录下的 build/webpack.prod.conf.js文件 js文件: output: { path: config.b ...

  6. vue 计算文件hash值_vue的hash值原理,也是table切换。

    .pages>div{display: none;} aaa bbb cccc 首页 关于我的页面 用户中心 //hash 和页面一一对应起来 //router 配置 var router = ...

  7. 【转】Java计算文件的hash值

    原文地址:http://blog.csdn.net/qq_25646191/article/details/78863110 如何知道一个文件是否改变了呢?当然是用比较文件hash值的方法,文件has ...

  8. Java计算文件的hash值

    如何知道一个文件是否改变了呢?当然是用比较文件hash值的方法,文件hash又叫文件签名,文件中哪怕一个bit位被改变了,文件hash就会不同. 比较常用的文件hash算法有MD5和SHA-1. 我用 ...

  9. sh256sum、xxd、base64联合计算文件的hash

    计算文件hash值并进行base64编码 # 计算文件的sha256哈西值 $ sha256sum filename f3b6d97538bf435399529405f5b5e88a81911d043 ...

最新文章

  1. ES6新增的let与const
  2. NoSql数据库使用半年后在设计上面的一些心得
  3. 华为MAC Flapping , MAC的漂移
  4. 完整议程、重磅嘉宾公布,第四范式AI新品发布会持续报名中
  5. 保存光谱曲线出现问题_直读光谱仪计量周期-这家好【博越仪器】
  6. 在SAP UI5应用里使用jQuery.ajax读取数据并显示在页面上
  7. code blocks c语言,Code Blocks安装与使用图文教程(使用Code::Blocks编写C语言程序)...
  8. linux祖先进程,Linux下的几种特殊进程
  9. 创建一个 Git 版本库
  10. JAVA 即时网络通信我的服务器
  11. 引用网易等相册的图片出现防盗链怎么办呢?看这里就迎刃而解!(转贴)
  12. git21天打卡Day1-linux下安装git
  13. 最新IOS审核被拒原因TOP10 | 附带解决方法
  14. FileStream:The process cannot access the file because it is being used by another process
  15. GoogleNet家族
  16. 大一计算机word排版试题,武汉大学大一计算机作业word排版
  17. 【UE4笔记】Collision碰撞
  18. 阿里云注册账号、购买云服务器、搭建网站全流程(图文教程)
  19. 【Android】RecycleView简单仿漫画APP图片相关样式
  20. Android基础——RecycleView

热门文章

  1. 跟着cryptokitties(以太坊云养猫)学写智能合约(上)
  2. 关于正则表达式的复习与总结
  3. 计算机右击管理在哪,电脑权限管理在哪里
  4. python写梦幻西游手游脚本辅助_3 行 python 代码帮你轻松实现” 自动发送测试报告 “到指定邮箱...
  5. python计算圆的周长和面积
  6. Improving Training of Text-to-image Model Using Mode-seeking Function
  7. 文章5:多功能智能跟随行李箱控制系统设计 | 本科毕业设计 - 【控制器的学习ARDUINO+STM32】
  8. 软件测试人员不知道这60个工具,直接损失一个亿
  9. 有一行电文,已按下面规律译成密码: A →Z B→Y C→X …… a→z b→y c→x …… 即第一个字母变成第26个字母,第i个字母变成第(26-i+1)个字母,非字母字
  10. 动态规划作业 最长单调递增子序列