通过计算它们的MD5获得重复的文件列表

本文关键字:列表 文件 MD5 计算 | 更新日期: 2023-09-27 18:01:44

我有一个数组,其中包含一个文件路径,我想列出那些基于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 的新手

通过计算它们的MD5获得重复的文件列表

1.重写calcMD5函数以接受单个文件路径,并返回MD5。
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);
}
    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();
            }
        }
    }

与其返回所有文件的MD5哈希数组,不如这样做:

  • 有一个单独的"calculateFileHash(("方法
  • 创建一个要测试的文件名数组
  • 这样做:

    var dupes=文件名.GroupBy(fn=>calculateFileHash(fn((。其中(gr=>gr.Count>1(;

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

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