C# 使用md5查找文件夹内重复的文件

本文介绍了一款用于文件去重及按创建日期重命名的实用工具。该工具使用MD5散列值来判断文件内容是否一致,并将重复文件移至指定文件夹。此外,还实现了文件的自动重命名功能,避免了因文件名冲突导致的操作失败。

思路:通过文件的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;
            }
        }
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值