2013-02-28 12 views
6

Mam tablicę, która zawiera ścieżkę plików, chcę utworzyć listę tych plików, które są duplikowane na podstawie ich MD5. I obliczyć ich MD5 tak:Uzyskaj zduplikowaną listę plików, obliczając ich 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; 
      } 
     } 
    }     
} 

Znad I stanie wyliczyć ich MD5 ale jak uzyskać tylko listę tych plików, które są podwójne. Jeśli istnieje jakikolwiek inny sposób zrobić to samo proszę dać mi znać, a także jestem nowy Linq

Odpowiedz

11

1. Przepisz swoją funkcję calcMD5 wziąć w pojedynczej ścieżki plik i powrotnej MD5.
2. Zachowaj nazwy plików w postaci string[] lub List<string>, a nie w tablicy bez typu, jeśli to możliwe.
3. Poniższa LINQ, aby uzyskać grupy plików z tym samym hash:

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

4. można dostać się do grup o zagnieżdżonych foreach pętli, na przykład:

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

wielkie dzięki @Rewling :) – Manish

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

który daje listę skrótów, które są powielane w tablicy.

Aby uzyskać nazwy zamiast skrótów, a także:

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

nie downvote, ale myślę, że chce listę zduplikowanych nazw plików, a nie powielane mieszań. –

+0

Zaktualizowałem swoją odpowiedź. – MarcinJuraszek

0

Zamiast Zwracanie tablica wszystkich plików skrótów MD5, zrób to w ten sposób:

  • Masz jedną całość Metoda lculateFileHash().
  • Utwórz tablicę nazw plików do przetestowania.
  • Wykonaj.

    var powtórzeń = Filenames.GroupBy (Fn => calculateFileHash (Fn)), gdzie (g => gr.Count> 1);

Spowoduje to wyświetlenie tablicy grup, przy czym każda grupa będzie wyliczalna i zawiera nazwy plików z identyczną zawartością.

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

To będzie sposób będzie działać szybko i wygląda na bardzo miły. Po użyciu 'listOfDuplicates', jak chcesz. – Maris

+0

'. Wybierz (e => e.First(). Wartość)' powoduje zwrócenie jednego duplikatu każdej grupy duplikatów. Zakładam, że nazwy plików nie są duplikatami, tylko ich skrótami. W przypadku, gdy w jednej grupie występują trzy duplikaty, informacje, które zwraca, są zupełnie bezużyteczne. Polecam '.SelectMany (e => e). Wybierz (e => e.Value) lub pozostaw je w całości zgrupowane. –

+0

To jest sposób, ale nie sądzę, że będzie wyglądać lepiej lub działać szybciej. Polecam użyć mojej pierwszej drogi. – Maris

Powiązane problemy