2009-05-06 19 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

+1

computeHashの呼び出しはストリーム上で動作するため、ファイルが大きい場合はメモリ内にすべて保持する必要はありません。 –

+0

ファイルを削除する前にファイルを閉じる必要はありませんか? – JonnyBoats

答えて

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

コードは動作しますが、私はn00bです。私はファイルをロックしていたMD5ハッシュの後にファイルを再利用していました。 – mattdwen

+0

悪い考えは?私は彼がなぜコードが機能していないのかを理解するのを助けました。大きなファイルをコピーしてロックされないようにすることは、世界の終わりではありません。彼のコードが実際に動作し、それを説明するためのサンプルを作成する彼の私の答えに間違っているとあなたは正確に何を言っていますか? @amin、あなたはもっと文脈を与えてくれますか? –

1

MD5オブジェクトをusing()でもラップしてみましたか?ドキュメントから、MD5は使い捨てです。それはそれがファイルを手放すかもしれない。

+0

ええ、おそらくファイル名を取り、ハッシュ文字列を返す関数を抽象化したいと思うでしょう。 – Mark

-1

ファイルを削除する前にmd5Hasherをnullに設定しようとしましたか?おそらくFileStream(メモリリーク)にまだハンドルが付いている可能性があります。

+2

変数をnullに設定しても、まだメモリに残っていて、一部のリソースを保持しているかどうかに直接影響はありません。ガベージコレクタとそのファイナライザは、変数をnullに設定するコードとそれ以降に続くコードのラインの間に入ることはまずありません。実際、コンパイラは、変数をnullに設定する行を無視することがあります。処分、ガベージコレクション、ファイナライズのいずれも引き起こさないでしょう。 –

-1

FileShare.ReadWriteでファイルを開いてみませんか?

0

md5hasher.Clear()あなたのループはこのトリックを行うかもしれません。

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(); 
} 
関連する問題