通过计算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; } } } }
从上面我能够计算他们的MD5,但是如何只获得那些重复的文件的列表。 如果还有其他方法可以让我知道,我也是Linq的新手
1.
重写calcMD5
函数以获取单个文件路径并返回 MD5。
2.
如果可能,将文件名存储在string[]
或List
,而不是非类型化数组。
3.
使用以下LINQ获取具有相同哈希的文件组:
var groupsOfFilesWithSameHash = files // or files.Cast() 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 CalcDuplicates(IEnumerable 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 = Filenames.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(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 hashToFilePathes = new Dictionary(); 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 listOfDuplicates = hashToFilePathes.GroupBy(e => e.Key).Where(e => e.Count() > 1).SelectMany(e=>e).Select(e => e.Value).ToList(); } }