Report Hash Progress
I am learning the MD5 hash values of the files through the code I have provided below. However, as the file size grows, the calculation takes a long time as well. I want to reflect this calculation on a progress bar object, but I have no idea.
I want something like this;
progressBar.Value = mD5.ComputedBytes;
progressBar.Maximum = mD5.TotalBytesToCompute;
How to make this?
Code;
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;
}
c# .net winforms hash md5
add a comment |
I am learning the MD5 hash values of the files through the code I have provided below. However, as the file size grows, the calculation takes a long time as well. I want to reflect this calculation on a progress bar object, but I have no idea.
I want something like this;
progressBar.Value = mD5.ComputedBytes;
progressBar.Maximum = mD5.TotalBytesToCompute;
How to make this?
Code;
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;
}
c# .net winforms hash md5
It's worth noting (from the MD5 Wikipedia article: en.wikipedia.org/wiki/MD5) that "The CMU Software Engineering Institute considers MD5 essentially 'cryptographically broken and unsuitable for further use'". You won't be able to show "progress" unless you can break the operation up into chunks (for example, if you were hashing 5 files, you could show 20% progress after each file). You can pop up an indefinite progress bar to show that work is happening, but you really can't show specific progress
– Flydog57
Dec 28 '18 at 23:57
1
HashAlgorithm
gives you the ability to hash data in chunks usingTransformBlock
andTransformFinalBlock
methods. In the other hand,Stream
class also allows you to read data in chunks asynchronously. Considering these facts, you can create a method to get a stream as input and then read stream in chunks and then for each chuck hash it and report the progress (percentage for example) by calculating bytes read.
– Reza Aghaei
Dec 29 '18 at 2:15
1
The solution is not limited to MD5, so you can use it for other hash algorithms as well.
– Reza Aghaei
Dec 29 '18 at 11:12
add a comment |
I am learning the MD5 hash values of the files through the code I have provided below. However, as the file size grows, the calculation takes a long time as well. I want to reflect this calculation on a progress bar object, but I have no idea.
I want something like this;
progressBar.Value = mD5.ComputedBytes;
progressBar.Maximum = mD5.TotalBytesToCompute;
How to make this?
Code;
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;
}
c# .net winforms hash md5
I am learning the MD5 hash values of the files through the code I have provided below. However, as the file size grows, the calculation takes a long time as well. I want to reflect this calculation on a progress bar object, but I have no idea.
I want something like this;
progressBar.Value = mD5.ComputedBytes;
progressBar.Maximum = mD5.TotalBytesToCompute;
How to make this?
Code;
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;
}
c# .net winforms hash md5
c# .net winforms hash md5
edited Dec 29 '18 at 15:27
Reza Aghaei
65.3k853158
65.3k853158
asked Dec 28 '18 at 23:27
Kelly BaileyKelly Bailey
226
226
It's worth noting (from the MD5 Wikipedia article: en.wikipedia.org/wiki/MD5) that "The CMU Software Engineering Institute considers MD5 essentially 'cryptographically broken and unsuitable for further use'". You won't be able to show "progress" unless you can break the operation up into chunks (for example, if you were hashing 5 files, you could show 20% progress after each file). You can pop up an indefinite progress bar to show that work is happening, but you really can't show specific progress
– Flydog57
Dec 28 '18 at 23:57
1
HashAlgorithm
gives you the ability to hash data in chunks usingTransformBlock
andTransformFinalBlock
methods. In the other hand,Stream
class also allows you to read data in chunks asynchronously. Considering these facts, you can create a method to get a stream as input and then read stream in chunks and then for each chuck hash it and report the progress (percentage for example) by calculating bytes read.
– Reza Aghaei
Dec 29 '18 at 2:15
1
The solution is not limited to MD5, so you can use it for other hash algorithms as well.
– Reza Aghaei
Dec 29 '18 at 11:12
add a comment |
It's worth noting (from the MD5 Wikipedia article: en.wikipedia.org/wiki/MD5) that "The CMU Software Engineering Institute considers MD5 essentially 'cryptographically broken and unsuitable for further use'". You won't be able to show "progress" unless you can break the operation up into chunks (for example, if you were hashing 5 files, you could show 20% progress after each file). You can pop up an indefinite progress bar to show that work is happening, but you really can't show specific progress
– Flydog57
Dec 28 '18 at 23:57
1
HashAlgorithm
gives you the ability to hash data in chunks usingTransformBlock
andTransformFinalBlock
methods. In the other hand,Stream
class also allows you to read data in chunks asynchronously. Considering these facts, you can create a method to get a stream as input and then read stream in chunks and then for each chuck hash it and report the progress (percentage for example) by calculating bytes read.
– Reza Aghaei
Dec 29 '18 at 2:15
1
The solution is not limited to MD5, so you can use it for other hash algorithms as well.
– Reza Aghaei
Dec 29 '18 at 11:12
It's worth noting (from the MD5 Wikipedia article: en.wikipedia.org/wiki/MD5) that "The CMU Software Engineering Institute considers MD5 essentially 'cryptographically broken and unsuitable for further use'". You won't be able to show "progress" unless you can break the operation up into chunks (for example, if you were hashing 5 files, you could show 20% progress after each file). You can pop up an indefinite progress bar to show that work is happening, but you really can't show specific progress
– Flydog57
Dec 28 '18 at 23:57
It's worth noting (from the MD5 Wikipedia article: en.wikipedia.org/wiki/MD5) that "The CMU Software Engineering Institute considers MD5 essentially 'cryptographically broken and unsuitable for further use'". You won't be able to show "progress" unless you can break the operation up into chunks (for example, if you were hashing 5 files, you could show 20% progress after each file). You can pop up an indefinite progress bar to show that work is happening, but you really can't show specific progress
– Flydog57
Dec 28 '18 at 23:57
1
1
HashAlgorithm
gives you the ability to hash data in chunks using TransformBlock
and TransformFinalBlock
methods. In the other hand, Stream
class also allows you to read data in chunks asynchronously. Considering these facts, you can create a method to get a stream as input and then read stream in chunks and then for each chuck hash it and report the progress (percentage for example) by calculating bytes read.– Reza Aghaei
Dec 29 '18 at 2:15
HashAlgorithm
gives you the ability to hash data in chunks using TransformBlock
and TransformFinalBlock
methods. In the other hand, Stream
class also allows you to read data in chunks asynchronously. Considering these facts, you can create a method to get a stream as input and then read stream in chunks and then for each chuck hash it and report the progress (percentage for example) by calculating bytes read.– Reza Aghaei
Dec 29 '18 at 2:15
1
1
The solution is not limited to MD5, so you can use it for other hash algorithms as well.
– Reza Aghaei
Dec 29 '18 at 11:12
The solution is not limited to MD5, so you can use it for other hash algorithms as well.
– Reza Aghaei
Dec 29 '18 at 11:12
add a comment |
1 Answer
1
active
oldest
votes
HashAlgorithm
gives you the ability to hash data in chunks using TransformBlock
and TransformFinalBlock
methods. In the other hand, Stream
class also allows you to read data in chunks asynchronously.
Considering these facts, you can create a method to get a stream as input and then read stream in chunks and then for each chuck hash it and report the progress (number of bytes processes) by calculating bytes read.
ComputeHashAsync
Here I've created a ComputeHashAsync
extension method for HashAlgorithm
class. It accepts:
stream
: inputStream
to compute hash.
cancellationToken
: an optionalCancellationToken
which can be used to cancel the operation
progress
: an optional instance ofIProgress<long>
which receives the progress report (number of bytes processed).
buggerSize
: an optional buffer size for reading data. The default id 1024*1024 bytes.
Here is the code:
using System;
using System.IO;
using System.Security.Cryptography;
using System.Threading;
using System.Threading.Tasks;
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;
}
}
Example 1 - Update 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));
}
}
Example 2 - Cancelling task after 1 second
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.");
}
Creating a large file for test
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();
}
Note: The implementation of computing hash in chunks, is taken from a blog post by Alexandre Gomes, then I changed the code to make it async
and support CancellationToken
and IProgress<long>
.
Hi, first of all, thank you very much for your reply. I'm not sure exactly how to use this code. Could you help me a bit? I created a "Hash.cs" named class for the first code and placed the lines of code in the class, but some lines seemed to be incorrect.
– Kelly Bailey
Dec 29 '18 at 14:05
Hi, you're welcome. About using the code, just create an empty.cs
code file and then copy my code in the file. Then everything should be fine and wherever you create an instance of your hash algorithm likemd5
, it will have aComputeHashAsync
method.
– Reza Aghaei
Dec 29 '18 at 14:11
This is how Extension Methods work in C#.
– Reza Aghaei
Dec 29 '18 at 14:13
1
.NET Framework >= 4.5
– Reza Aghaei
Dec 29 '18 at 14:48
1
Hello! I'm not sure, but passingfs.Length
to theInvoke
is not good idea, because it may be accessed while the fs is closed. Instead, put it in a variable and pass the variable.
– Reza Aghaei
Dec 29 '18 at 19:36
|
show 14 more comments
Your Answer
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53965380%2freport-hash-progress%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
1 Answer
1
active
oldest
votes
1 Answer
1
active
oldest
votes
active
oldest
votes
active
oldest
votes
HashAlgorithm
gives you the ability to hash data in chunks using TransformBlock
and TransformFinalBlock
methods. In the other hand, Stream
class also allows you to read data in chunks asynchronously.
Considering these facts, you can create a method to get a stream as input and then read stream in chunks and then for each chuck hash it and report the progress (number of bytes processes) by calculating bytes read.
ComputeHashAsync
Here I've created a ComputeHashAsync
extension method for HashAlgorithm
class. It accepts:
stream
: inputStream
to compute hash.
cancellationToken
: an optionalCancellationToken
which can be used to cancel the operation
progress
: an optional instance ofIProgress<long>
which receives the progress report (number of bytes processed).
buggerSize
: an optional buffer size for reading data. The default id 1024*1024 bytes.
Here is the code:
using System;
using System.IO;
using System.Security.Cryptography;
using System.Threading;
using System.Threading.Tasks;
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;
}
}
Example 1 - Update 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));
}
}
Example 2 - Cancelling task after 1 second
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.");
}
Creating a large file for test
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();
}
Note: The implementation of computing hash in chunks, is taken from a blog post by Alexandre Gomes, then I changed the code to make it async
and support CancellationToken
and IProgress<long>
.
Hi, first of all, thank you very much for your reply. I'm not sure exactly how to use this code. Could you help me a bit? I created a "Hash.cs" named class for the first code and placed the lines of code in the class, but some lines seemed to be incorrect.
– Kelly Bailey
Dec 29 '18 at 14:05
Hi, you're welcome. About using the code, just create an empty.cs
code file and then copy my code in the file. Then everything should be fine and wherever you create an instance of your hash algorithm likemd5
, it will have aComputeHashAsync
method.
– Reza Aghaei
Dec 29 '18 at 14:11
This is how Extension Methods work in C#.
– Reza Aghaei
Dec 29 '18 at 14:13
1
.NET Framework >= 4.5
– Reza Aghaei
Dec 29 '18 at 14:48
1
Hello! I'm not sure, but passingfs.Length
to theInvoke
is not good idea, because it may be accessed while the fs is closed. Instead, put it in a variable and pass the variable.
– Reza Aghaei
Dec 29 '18 at 19:36
|
show 14 more comments
HashAlgorithm
gives you the ability to hash data in chunks using TransformBlock
and TransformFinalBlock
methods. In the other hand, Stream
class also allows you to read data in chunks asynchronously.
Considering these facts, you can create a method to get a stream as input and then read stream in chunks and then for each chuck hash it and report the progress (number of bytes processes) by calculating bytes read.
ComputeHashAsync
Here I've created a ComputeHashAsync
extension method for HashAlgorithm
class. It accepts:
stream
: inputStream
to compute hash.
cancellationToken
: an optionalCancellationToken
which can be used to cancel the operation
progress
: an optional instance ofIProgress<long>
which receives the progress report (number of bytes processed).
buggerSize
: an optional buffer size for reading data. The default id 1024*1024 bytes.
Here is the code:
using System;
using System.IO;
using System.Security.Cryptography;
using System.Threading;
using System.Threading.Tasks;
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;
}
}
Example 1 - Update 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));
}
}
Example 2 - Cancelling task after 1 second
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.");
}
Creating a large file for test
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();
}
Note: The implementation of computing hash in chunks, is taken from a blog post by Alexandre Gomes, then I changed the code to make it async
and support CancellationToken
and IProgress<long>
.
Hi, first of all, thank you very much for your reply. I'm not sure exactly how to use this code. Could you help me a bit? I created a "Hash.cs" named class for the first code and placed the lines of code in the class, but some lines seemed to be incorrect.
– Kelly Bailey
Dec 29 '18 at 14:05
Hi, you're welcome. About using the code, just create an empty.cs
code file and then copy my code in the file. Then everything should be fine and wherever you create an instance of your hash algorithm likemd5
, it will have aComputeHashAsync
method.
– Reza Aghaei
Dec 29 '18 at 14:11
This is how Extension Methods work in C#.
– Reza Aghaei
Dec 29 '18 at 14:13
1
.NET Framework >= 4.5
– Reza Aghaei
Dec 29 '18 at 14:48
1
Hello! I'm not sure, but passingfs.Length
to theInvoke
is not good idea, because it may be accessed while the fs is closed. Instead, put it in a variable and pass the variable.
– Reza Aghaei
Dec 29 '18 at 19:36
|
show 14 more comments
HashAlgorithm
gives you the ability to hash data in chunks using TransformBlock
and TransformFinalBlock
methods. In the other hand, Stream
class also allows you to read data in chunks asynchronously.
Considering these facts, you can create a method to get a stream as input and then read stream in chunks and then for each chuck hash it and report the progress (number of bytes processes) by calculating bytes read.
ComputeHashAsync
Here I've created a ComputeHashAsync
extension method for HashAlgorithm
class. It accepts:
stream
: inputStream
to compute hash.
cancellationToken
: an optionalCancellationToken
which can be used to cancel the operation
progress
: an optional instance ofIProgress<long>
which receives the progress report (number of bytes processed).
buggerSize
: an optional buffer size for reading data. The default id 1024*1024 bytes.
Here is the code:
using System;
using System.IO;
using System.Security.Cryptography;
using System.Threading;
using System.Threading.Tasks;
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;
}
}
Example 1 - Update 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));
}
}
Example 2 - Cancelling task after 1 second
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.");
}
Creating a large file for test
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();
}
Note: The implementation of computing hash in chunks, is taken from a blog post by Alexandre Gomes, then I changed the code to make it async
and support CancellationToken
and IProgress<long>
.
HashAlgorithm
gives you the ability to hash data in chunks using TransformBlock
and TransformFinalBlock
methods. In the other hand, Stream
class also allows you to read data in chunks asynchronously.
Considering these facts, you can create a method to get a stream as input and then read stream in chunks and then for each chuck hash it and report the progress (number of bytes processes) by calculating bytes read.
ComputeHashAsync
Here I've created a ComputeHashAsync
extension method for HashAlgorithm
class. It accepts:
stream
: inputStream
to compute hash.
cancellationToken
: an optionalCancellationToken
which can be used to cancel the operation
progress
: an optional instance ofIProgress<long>
which receives the progress report (number of bytes processed).
buggerSize
: an optional buffer size for reading data. The default id 1024*1024 bytes.
Here is the code:
using System;
using System.IO;
using System.Security.Cryptography;
using System.Threading;
using System.Threading.Tasks;
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;
}
}
Example 1 - Update 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));
}
}
Example 2 - Cancelling task after 1 second
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.");
}
Creating a large file for test
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();
}
Note: The implementation of computing hash in chunks, is taken from a blog post by Alexandre Gomes, then I changed the code to make it async
and support CancellationToken
and IProgress<long>
.
edited Dec 29 '18 at 17:29
Ahmed Abdelhameed
5,58882046
5,58882046
answered Dec 29 '18 at 2:08
Reza AghaeiReza Aghaei
65.3k853158
65.3k853158
Hi, first of all, thank you very much for your reply. I'm not sure exactly how to use this code. Could you help me a bit? I created a "Hash.cs" named class for the first code and placed the lines of code in the class, but some lines seemed to be incorrect.
– Kelly Bailey
Dec 29 '18 at 14:05
Hi, you're welcome. About using the code, just create an empty.cs
code file and then copy my code in the file. Then everything should be fine and wherever you create an instance of your hash algorithm likemd5
, it will have aComputeHashAsync
method.
– Reza Aghaei
Dec 29 '18 at 14:11
This is how Extension Methods work in C#.
– Reza Aghaei
Dec 29 '18 at 14:13
1
.NET Framework >= 4.5
– Reza Aghaei
Dec 29 '18 at 14:48
1
Hello! I'm not sure, but passingfs.Length
to theInvoke
is not good idea, because it may be accessed while the fs is closed. Instead, put it in a variable and pass the variable.
– Reza Aghaei
Dec 29 '18 at 19:36
|
show 14 more comments
Hi, first of all, thank you very much for your reply. I'm not sure exactly how to use this code. Could you help me a bit? I created a "Hash.cs" named class for the first code and placed the lines of code in the class, but some lines seemed to be incorrect.
– Kelly Bailey
Dec 29 '18 at 14:05
Hi, you're welcome. About using the code, just create an empty.cs
code file and then copy my code in the file. Then everything should be fine and wherever you create an instance of your hash algorithm likemd5
, it will have aComputeHashAsync
method.
– Reza Aghaei
Dec 29 '18 at 14:11
This is how Extension Methods work in C#.
– Reza Aghaei
Dec 29 '18 at 14:13
1
.NET Framework >= 4.5
– Reza Aghaei
Dec 29 '18 at 14:48
1
Hello! I'm not sure, but passingfs.Length
to theInvoke
is not good idea, because it may be accessed while the fs is closed. Instead, put it in a variable and pass the variable.
– Reza Aghaei
Dec 29 '18 at 19:36
Hi, first of all, thank you very much for your reply. I'm not sure exactly how to use this code. Could you help me a bit? I created a "Hash.cs" named class for the first code and placed the lines of code in the class, but some lines seemed to be incorrect.
– Kelly Bailey
Dec 29 '18 at 14:05
Hi, first of all, thank you very much for your reply. I'm not sure exactly how to use this code. Could you help me a bit? I created a "Hash.cs" named class for the first code and placed the lines of code in the class, but some lines seemed to be incorrect.
– Kelly Bailey
Dec 29 '18 at 14:05
Hi, you're welcome. About using the code, just create an empty
.cs
code file and then copy my code in the file. Then everything should be fine and wherever you create an instance of your hash algorithm like md5
, it will have a ComputeHashAsync
method.– Reza Aghaei
Dec 29 '18 at 14:11
Hi, you're welcome. About using the code, just create an empty
.cs
code file and then copy my code in the file. Then everything should be fine and wherever you create an instance of your hash algorithm like md5
, it will have a ComputeHashAsync
method.– Reza Aghaei
Dec 29 '18 at 14:11
This is how Extension Methods work in C#.
– Reza Aghaei
Dec 29 '18 at 14:13
This is how Extension Methods work in C#.
– Reza Aghaei
Dec 29 '18 at 14:13
1
1
.NET Framework >= 4.5
– Reza Aghaei
Dec 29 '18 at 14:48
.NET Framework >= 4.5
– Reza Aghaei
Dec 29 '18 at 14:48
1
1
Hello! I'm not sure, but passing
fs.Length
to the Invoke
is not good idea, because it may be accessed while the fs is closed. Instead, put it in a variable and pass the variable.– Reza Aghaei
Dec 29 '18 at 19:36
Hello! I'm not sure, but passing
fs.Length
to the Invoke
is not good idea, because it may be accessed while the fs is closed. Instead, put it in a variable and pass the variable.– Reza Aghaei
Dec 29 '18 at 19:36
|
show 14 more comments
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53965380%2freport-hash-progress%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
It's worth noting (from the MD5 Wikipedia article: en.wikipedia.org/wiki/MD5) that "The CMU Software Engineering Institute considers MD5 essentially 'cryptographically broken and unsuitable for further use'". You won't be able to show "progress" unless you can break the operation up into chunks (for example, if you were hashing 5 files, you could show 20% progress after each file). You can pop up an indefinite progress bar to show that work is happening, but you really can't show specific progress
– Flydog57
Dec 28 '18 at 23:57
1
HashAlgorithm
gives you the ability to hash data in chunks usingTransformBlock
andTransformFinalBlock
methods. In the other hand,Stream
class also allows you to read data in chunks asynchronously. Considering these facts, you can create a method to get a stream as input and then read stream in chunks and then for each chuck hash it and report the progress (percentage for example) by calculating bytes read.– Reza Aghaei
Dec 29 '18 at 2:15
1
The solution is not limited to MD5, so you can use it for other hash algorithms as well.
– Reza Aghaei
Dec 29 '18 at 11:12