代码之家  ›  专栏  ›  技术社区  ›  Manish

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

  •  7
  • Manish  · 技术社区  · 13 年前

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

    5 回复  |  直到 13 年前
        1
  •  11
  •   Rawling isekaijin    13 年前

    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);
    }
    
        2
  •  2
  •   Michael Schnerring    13 年前
        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();
                }
            }
        }
    
        3
  •  0
  •   PhonicUK    13 年前

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

    • 有一个单独的“calculateFileHash()”方法。
    • 创建一个要测试的文件名数组。
    • 执行以下操作:

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

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

        4
  •  0
  •   Bort    13 年前
    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());
    
        5
  •  0
  •   Maris    13 年前
        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();
        }
    }