2013-02-28 10 views
6

私はファイルパスを含む配列を持っていますが、そのMD5に基づいて重複しているファイルをリストにしたいと思います。私はこのような彼らのMD5を計算する:MD5を計算して重複ファイルリストを取得

private void calcMD5(Array files) //Array contains a path of all files 
{ 
    int i=0; 
    string[] md5_val = new string[files.Length]; 
    foreach (string file_name in files) 
    { 
     using (var md5 = MD5.Create()) 
     { 
      using (var stream = File.OpenRead(file_name)) 
      { 
       md5_val[i] = BitConverter.ToString(md5.ComputeHash(stream)).Replace("-", "").ToLower(); 
       i += 1; 
      } 
     } 
    }     
} 

I以上のことから彼らのMD5を計算することができるが、どのよう重複しているこれらのファイルのリストだけを取得します。行うには、他の方法がある場合は、同じ私に知らせて、そしてまた、私はあなたに、配列内で重複しているハッシュのリストが表示されますLINQの

答えて

11

単一ファイルのパスとリターン MD5に取るようにあなたのcalcMD5機能を書き換え1.
2.ファイル名は、可能であればタイプなしの配列ではなく、string[]またはList<string>に格納します。
3.同じハッシュでファイルのグループを取得するには、次のLINQを使用します。

var groupsOfFilesWithSameHash = files 
    // or files.Cast<string>() if you're stuck with an Array 
    .GroupBy(f => calcMD5(f)) 
    .Where(g => g.Count() > 1); 

4.あなたは、たとえば、ネストされたforeachループでグループに取得することができます。

foreach(var group in groupsOfFilesWithSameHash) 
{ 
    Console.WriteLine("Shared MD5: " + g.Key); 
    foreach (var file in group) 
     Console.WriteLine(" " + file); 
} 
+0

多くのありがとう@Rawling :) – Manish

0
var duplicates = md5_val.GroupBy(x => x).Where(x => x.Count() > 1).Select(x => x.Key); 

に新しいですしてください。

は、同様の名前の代わりに、ハッシュを取得するには:

var duplicates = md5_val.Select((x,i) => new Tuple<string, int>(x, i)) 
         .GroupBy(x => x.Item1) 
         .Where(x => x.Count() > 1) 
         .SelectMany(x => files[x.Item2].ToList()); 
+0

私はdownvoteませんでしたが、私は彼が重複したファイル名ではなく、重複ハッシュのリストを望んでいると思います。 –

+0

私は自分の答えを更新しました。 – MarcinJuraszek

0

代わりの戻りをMD5ハッシュのすべてのファイルの配列、代わりにこのように:

  • lculateFileHash()メソッドです。
  • テストするファイル名の配列を作成します。
  • これを行います。

    するvar dupesを= Filenames.GroupBy(FN => calculateFileHash(FN))ここで、(GR => gr.Count> 1);

これはグループの配列を返します。各グループは、同じ内容のファイル名を含む列挙型です。

2
static void Main(string[] args) 
    { 
     // returns a list of file names, which have duplicate MD5 hashes 
     var duplicates = CalcDuplicates(new[] {"Hello.txt", "World.txt"}); 
    } 

    private static IEnumerable<string> CalcDuplicates(IEnumerable<string> fileNames) 
    { 
     return fileNames.GroupBy(CalcMd5OfFile) 
         .Where(g => g.Count() > 1) 
         // skip SelectMany() if you'd like the duplicates grouped by their hashes as group key 
         .SelectMany(g => g); 
    } 

    private static string CalcMd5OfFile(string path) 
    { 
     // I took your implementation - I don't know if there are better ones 
     using (var md5 = MD5.Create()) 
     { 
      using (var stream = File.OpenRead(path)) 
      { 
       return BitConverter.ToString(md5.ComputeHash(stream)).Replace("-", "").ToLower(); 
      } 
     } 
    } 
0
private void calcMD5(String[] filePathes) //Array contains a path of all files 
    { 
     Dictionary<String, String> hashToFilePathes = new Dictionary<String, String>(); 
     foreach (string file_name in filePathes) 
     { 
      using (var md5 = MD5.Create()) 
      { 
       using (var stream = File.OpenRead(file_name)) 
       { 
        //This will get you dictionary where key is md5hash and value is filepath 
        hashToFilePathes.Add(BitConverter.ToString(md5.ComputeHash(stream)).Replace("-", "").ToLower(), file_name); 
       } 
      } 
     } 
     // Here will be all duplicates 
     List<String> listOfDuplicates = hashToFilePathes.GroupBy(e => e.Key).Where(e => e.Count() > 1).SelectMany(e=>e).Select(e => e.Value).ToList(); 
    } 
} 
+0

これは方法が速く動作し、多くの素晴らしいに見えます。後であなたが望むように 'listOfDuplicates'を使うことができます。 – Maris

+0

'.Select(e => e.First()。Value)'は、重複の各グループの1つの重複を返します。私は、ファイル名が重複ではなく、ハッシュだけであると仮定します。したがって、1つのグループに3つの重複がある場合、それが返す情報はまったく役に立たない。私は '.SelectMany(e => e).Select(e => e.Value)'をお勧めします。 –

+0

それは方法ですが、私はそれがより良く見えるか、より速く動作するとは思わない。私は最初の方法を使用することをお勧めします。 – Maris

関連する問題