Kel*_*ley 1 .net c# hash md5 winforms
我通过下面提供的代码学习文件的MD5哈希值.但是,随着文件大小的增加,计算也需要很长时间.我想在进度条对象上反映这个计算,但我不知道.
我想要这样的东西;
progressBar.Value = mD5.ComputedBytes;
progressBar.Maximum = mD5.TotalBytesToCompute;
Run Code Online (Sandbox Code Playgroud)
怎么做到这个?
码;
public static string getMD5HashFromFile(string fileName)
{
string str = "";
using (MD5 mD5 = MD5.Create())
{
using (FileStream fileStream = File.OpenRead(fileName))
{ str = BitConverter.ToString(mD5.ComputeHash(fileStream)).Replace("-", string.Empty); fileStream.Close(); }
}
return str;
}
Run Code Online (Sandbox Code Playgroud)
HashAlgorithm使您能够使用TransformBlock和TransformFinalBlock方法在块中散列数据.另一方面,Stream类也允许您以异步方式读取数据块.
考虑到这些事实,您可以创建一个方法来获取流作为输入,然后以块的形式读取流,然后对每个chuck散列它并通过计算读取的字节来报告进度(字节进程数).
ComputeHashAsync
在这里,我ComputeHashAsync为HashAlgorithm类创建了一个扩展方法.它接受:
stream:输入Stream计算哈希值.cancellationToken:可选的CancellationToken,可用于取消操作progress:其可选实例IProgress<long>接收进度报告(已处理的字节数).buggerSize:用于读取数据的可选缓冲区大小.默认id为1024*1024字节.这是代码:
using System;
using System.IO;
using System.Security.Cryptography;
using System.Threading;
using System.Threading.Tasks;
Run Code Online (Sandbox Code Playgroud)
public static class HashAlgorithmExtensions {
public static async Task<byte[]> ComputeHashAsync(
this HashAlgorithm hashAlgorithm, Stream stream,
CancellationToken cancellationToken = default(CancellationToken),
IProgress<long> progress = null,
int bufferSize = 1024 * 1024) {
byte[] readAheadBuffer, buffer, hash;
int readAheadBytesRead, bytesRead;
long size, totalBytesRead = 0;
size = stream.Length;
readAheadBuffer = new byte[bufferSize];
readAheadBytesRead = await stream.ReadAsync(readAheadBuffer, 0,
readAheadBuffer.Length, cancellationToken);
totalBytesRead += readAheadBytesRead;
do {
bytesRead = readAheadBytesRead;
buffer = readAheadBuffer;
readAheadBuffer = new byte[bufferSize];
readAheadBytesRead = await stream.ReadAsync(readAheadBuffer, 0,
readAheadBuffer.Length, cancellationToken);
totalBytesRead += readAheadBytesRead;
if (readAheadBytesRead == 0)
hashAlgorithm.TransformFinalBlock(buffer, 0, bytesRead);
else
hashAlgorithm.TransformBlock(buffer, 0, bytesRead, buffer, 0);
if (progress != null)
progress.Report(totalBytesRead);
if (cancellationToken.IsCancellationRequested)
cancellationToken.ThrowIfCancellationRequested();
} while (readAheadBytesRead != 0);
return hash = hashAlgorithm.Hash;
}
}
Run Code Online (Sandbox Code Playgroud)
示例1 - 更新ProgressBar
byte[] bytes;
using (var hash = MD5.Create())
{
using (var fs = new FileStream(f, FileMode.Open))
{
bytes = await hash.ComputeHashAsync(fs,
progress: new Progress<long>(i =>
{
progressBar1.Invoke(new Action(() =>
{
progressBar1.Value = i;
}));
}));
MessageBox.Show(BitConverter.ToString(bytes).Replace("-", string.Empty));
}
}
Run Code Online (Sandbox Code Playgroud)
示例2 - 1秒后取消任务
try
{
var s = new CancellationTokenSource();
s.CancelAfter(1000);
byte[] bytes;
using (var hash = MD5.Create())
{
using (var fs = new FileStream(f, FileMode.Open))
{
bytes = await hash.ComputeHashAsync(fs,
cancellationToken: s.Token,
progress: new Progress<long>(i =>
{
progressBar1.Invoke(new Action(() =>
{
progressBar1.Value = i;
}));
}));
MessageBox.Show(BitConverter.ToString(bytes).Replace("-", string.Empty));
}
}
}
catch (OperationCanceledException)
{
MessageBox.Show("Operation canceled.");
}
Run Code Online (Sandbox Code Playgroud)
创建一个大文件进行测试
var f = Path.Combine(Application.StartupPath, "temp.log");
File.Delete(f);
using (var fs = new FileStream(f, FileMode.Create))
{
fs.Seek(1L * 1024 * 1024 * 1024, SeekOrigin.Begin);
fs.WriteByte(0);
fs.Close();
}
Run Code Online (Sandbox Code Playgroud)
注意:在块中计算哈希的实现取自Alexandre Gomes 的博客文章,然后我更改了代码以使其async支持CancellationToken和IProgress<long>.