7

我有一个包含文件路径的数组,我想列出一个基于 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;
            }
        }
    }                
}

从上面我可以计算出他们的 MD5,但是如何只获取那些重复的文件的列表。如果还有其他方法可以做同样的事情,请告诉我,我也是 Linq 的新手

4

5 回答 5

11

1.重写您的calcMD5函数以获取单个文件路径并返回MD5。
2.如果可能,将文件名存储在string[]orList<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);
}
于 2013-02-28T11:16:29.270 回答
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();
            }
        }
    }
于 2013-02-28T11:22:14.477 回答
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());
于 2013-02-28T11:12:57.313 回答
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();
    }
} 
于 2013-02-28T11:28:48.593 回答
0

不要返回所有文件 MD5 哈希的数组,而是这样做:

  • 有一个“calculateFileHash()”方法。
  • 创建要测试的文件名数组。
  • 做这个:

    var dupes = Filenames.GroupBy(fn => calculateFileHash(fn)).Where(gr => gr.Count > 1);

这将返回一个组数组,每个组都是一个可枚举,其中包含彼此具有相同内容的文件名。

于 2013-02-28T11:17:48.627 回答