2009-05-06 100 views
12

編輯:作爲代碼按預期工作,我改名這一個例子。C#MD5散列器例如

我試圖複製一個文件,得到一個MD5哈希值,然後刪除該副本。我這樣做是爲了避免另一個應用程序寫入的原始文件上的進程鎖。但是,我正在鎖定我複製的文件。

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

我再得到一個「進程無法訪問文件」上File.Delete()例外」。

我期望與using說法,文件流將很好地關閉。我也嘗試單獨宣佈文件流,刪除using,並在讀取後將fs.Close()fs.Dispose()

在此之後,我註釋了實際的md5計算,並且代碼在刪除文件的情況下執行,因此它看起來像是與ComputeHash(fs)有關。

+1

爲什麼不直接調用ReadAllBytes()並完成它? – BobbyShaftoe 2009-05-06 00:27:31

+1

因爲他對computeHash的調用在流上運行 - 如果文件很大,他不需要將它全部保存在內存中。 – 2009-05-06 00:35:05

+0

在您付款之前,您是否需要關閉該文件? – JonnyBoats 2009-05-06 00:53:19

回答

15

我把你的代碼把它在一個控制檯應用程序並沒有錯誤運行它,得到了哈希和測試文件在執行結束時刪除嗎?我剛剛使用我的測試應用程序中的.pdb作爲文件。

你正在運行的是什麼版本的.NET?

我把,我有一個在這裏工作,如果你把這個在一個控制檯應用程序在VS2008 .NET 3.5 SP1它不出差錯運行(至少對我來說)的代碼。

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

你是否嘗試用using()包裝MD5對象?從文檔中,MD5是一次性的。這可能會讓它放棄文件。

+0

是的,你可能想抽象一個接受文件名並返回一個哈希字符串的函數。 – Mark 2009-05-06 00:35:52

-1

您是否曾嘗試在刪除文件之前將md5Hasher設置爲null?它可能有一個仍附加到FileStream的句柄(也許是內存泄漏)。

-1

爲什麼不用FileShare.ReadWrite打開文件?

20

導入名字空間

using System.Security.Cryptography; 

這裏是返回你的MD5哈希碼的功能。您需要傳遞字符串作爲參數。

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