Reputation: 5428
Edit: I've retitled this to an example as the code works as expected.
I am trying to copy a file, get a MD5 hash, then delete the copy. I am doing this to avoid process locks on the original file, which another app writes to. However, I am getting a lock on the file I've copied.
File.Copy(pathSrc, pathDest, true);
String md5Result;
StringBuilder sb = new StringBuilder();
MD5 md5Hasher = MD5.Create();
using (FileStream fs = File.OpenRead(pathDest))
{
foreach(Byte b in md5Hasher.ComputeHash(fs))
sb.Append(b.ToString("x2").ToLower());
}
md5Result = sb.ToString();
File.Delete(pathDest);
I am then getting a 'process cannot access the file' exception on File.Delete()
'.
I would expect that with the using
statement, the filestream would be closed nicely. I have also tried declaring the filestream separately, removing using
, and putting fs.Close()
and fs.Dispose()
after the read.
After this, I commented out the actually md5 computation, and the code excutes, with the file being deleted, so it looks like it's something to do with ComputeHash(fs)
.
Upvotes: 12
Views: 48730
Reputation: 458
Import the name space
using System.Security.Cryptography;
Here is the function that returns you md5 hash code. You need to pass the string as parameter.
public static string GetMd5Hash(string input)
{
MD5 md5Hash = MD5.Create();
// Convert the input string to a byte array and compute the hash.
byte[] data = md5Hash.ComputeHash(Encoding.UTF8.GetBytes(input));
// Create a new Stringbuilder to collect the bytes
// and create a string.
StringBuilder sBuilder = new StringBuilder();
// Loop through each byte of the hashed data
// and format each one as a hexadecimal string.
for (int i = 0; i < data.Length; i++)
{
sBuilder.Append(data[i].ToString("x2"));
}
// Return the hexadecimal string.
return sBuilder.ToString();
}
Upvotes: 20
Reputation: 4339
I took your code put it in a console app and ran it with no errors, got the hash and the test file is deleted at the end of execution? I just used the .pdb from my test app as the file.
What version of .NET are you running?
I am putting the code that I have that works here, and if you put this in a console app in VS2008 .NET 3.5 sp1 it runs with no errors (at least for me).
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Security.Cryptography;
using System.IO;
namespace lockTest
{
class Program
{
static void Main(string[] args)
{
string hash = GetHash("lockTest.pdb");
Console.WriteLine("Hash: {0}", hash);
Console.ReadKey();
}
public static string GetHash(string pathSrc)
{
string pathDest = "copy_" + pathSrc;
File.Copy(pathSrc, pathDest, true);
String md5Result;
StringBuilder sb = new StringBuilder();
MD5 md5Hasher = MD5.Create();
using (FileStream fs = File.OpenRead(pathDest))
{
foreach (Byte b in md5Hasher.ComputeHash(fs))
sb.Append(b.ToString("x2").ToLower());
}
md5Result = sb.ToString();
File.Delete(pathDest);
return md5Result;
}
}
}
Upvotes: 15
Reputation: 7306
Have you tried setting md5Hasher to null before deleting the file? It probably has a handle still attached to the FileStream (memory leak perhaps).
Upvotes: -1
Reputation: 5412
Did you try wrapping your MD5 object in a using() too? From the docs, MD5 is Disposable. That might make it let go of the file.
Upvotes: 1