C# MD5 hasher example

47,822

Solution 1

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;
        }
    }
}

Solution 2

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();
}

Solution 3

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.

Share:
47,822
mattdwen
Author by

mattdwen

Updated on July 05, 2022

Comments

  • mattdwen
    mattdwen almost 2 years

    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).

  • Mark
    Mark about 15 years
    Yeah, you probably want to abstract a function that takes a filename and returns a hash string.
  • Josh Gallagher
    Josh Gallagher almost 11 years
    Setting a variable to null has no immediate effect on whether it is still in memory and still holding onto some resources. The garbage collector and its finalizer are highly unlikely to kick in between setting code that sets a variable to null and lines of code the follow on from that. In fact, the compiler may well ignore the line that sets the variable to null. It will certainly not trigger either disposal, garbage collection or finalization.
  • Brian ONeil
    Brian ONeil over 9 years
    What is a bad idea? I helped him figure out why the code wasn't working. Copying a large file to keep it from being locked is not the end of the world. What exactly are you saying is wrong with my answer to him that his code actually works and creating a sample to illustrate it? @amin, Can you please give more context?