思路:通过文件的md5值和大小,判断文件是否相同。
using System.Collections.Generic;
using System.Security.Cryptography;
using System.IO;
public static class FileTool
{
// 文件检索目录
private const string DirPath = "";
// 重复文件的存放目录
private const string SameFilesPath = "";
private static void FindSameFiles()
{
var rootDirInfo = new DirectoryInfo(DirPath);
var fileInfoList = new List<FileInfo>();
// 找到所有文件
var fileInfos = rootDirInfo.GetFiles("*.*");
var total = fileInfos.Length;
var index = 0;
for (var i = 0; i < total; ++i)
{
var fileInfo = fileInfos[i];
var time = fileInfo.CreationTime.ToString("yyyy-MM-dd-HHmmss");
// 存储文件,以备后用
fileInfoList.Add(fileInfo);
// 根据文件创建日期重命名文件
// 这是一个递归函数,如果日期名称相同,则增加名称中的计数器
TryNaming(fileInfo, time, 0);
// 显示重命名进度
DisplayProgressBar
(
"Renaming Files",
$"Progress {++index} / {total}",
index / (float) total
);
}
// 存储每个文件的md5字符串
var md5Strs = new string[total];
// 存储相同的文件
var sameFileInfos = new List<FileInfo>();
var md5 = new MD5CryptoServiceProvider();
for (var j = 0; j < total; ++j)
{
if (md5Strs[j] == null)
{
// 对应位置的文件没有md5则生成
md5Strs[j] = GetMd5Str(md5, fileInfoList[j]);
}
// 记录当前相同文件个数,以备后续判断,是否增加了相同文件
var curSameCount = sameFileInfos.Count;
// 对比j之后的每一个文件,与之前的文件的对比,在之前文件的循环中对比过
for (var k = j + 1; k < total; ++k)
{
// 只检测大小相同文件的md5
if (fileInfoList[k].Length == fileInfoList[j].Length)
{
if (md5Strs[k] == null)
{
// 对应位置的文件没有md5则生成
md5Strs[k] = GetMd5Str(md5, fileInfoList[k]);
}
if (md5Strs[k] == md5Strs[j])
{
// 找到相同文件
sameFileInfos.Add(fileInfoList[k]);
}
}
}
if (sameFileInfos.Count > curSameCount)
{
// 如果有相同文件,则把对比文件放入
sameFileInfos.Add(fileInfoList[j]);
}
// 显示对比进度
DisplayProgressBar
(
$"Comparing Files",
$"Progress {j} / {total}",
j / (float) total
);
}
// 显示相同文件数量
DisplayDialog("Result", $"same files count = {sameFileInfos.Count}", "ok");
// 移动相同文件到指定目录
foreach (var fileInfo in sameFileInfos)
{
fileInfo.MoveTo(SameFilesPath + "/" + fileInfo.Name);
}
}
private static string GetMd5Str(MD5CryptoServiceProvider md5, FileInfo fileInfo)
{
var stream = fileInfo.OpenRead();
var bytes = md5.ComputeHash(stream);
stream.Close();
return System.BitConverter.ToString(bytes).Replace("-", "");
}
private static void TryNaming(FileInfo fileInfo, string time, int sameCount)
{
var timeName = time + "-" + sameCount + fileInfo.Extension;
if (fileInfo.Name == timeName)
{
return;
}
try
{
fileInfo.MoveTo(fileInfo.DirectoryName + "/" + timeName);
}
catch (IOException e)
{
// have same names
if (e.Message == "Error 183")
{
TryNaming(fileInfo, time, ++sameCount);
}
else
{
throw e;
}
}
}
}