通过计算它们的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 的新手
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();
}
}