C#实现文件夹重复文件比对 进度百分比统计不准确如何解决?
问题根源
- 总任务量统计错误:将两个文件夹的文件数之和作为进度计算的分母,但嵌套循环逻辑实际会产生
M*N次重复的哈希计算操作,总操作量远大于设定的分母,导致进度计算完全失真。 - 进度更新时机错误:进度打印逻辑只放在外层循环末尾,内层循环处理第二个文件夹文件时不会更新进度,会出现进度跳变、显示不准的问题。
- 额外性能冗余:内层循环每次都会重复计算第一个文件夹当前文件的哈希,完全无意义,会导致执行效率随文件数量上升极速下降。
修复方案
先调整比对逻辑降低时间复杂度,再修正进度统计逻辑:
- 提前预计算第二个文件夹所有文件的哈希并存储到字典,避免嵌套循环
- 总任务量设为两个文件夹的文件总数,每完成一个文件的哈希计算就更新一次进度
- 进度更新时机调整为每次处理完单个文件后
修复后代码
using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Security.Cryptography; namespace mvp { class Program { public static string ComputeHash(string filename) { using (HashAlgorithm algorithm = HashAlgorithm.Create("SHA1")) { try { using (FileStream fs = new FileStream(filename, FileMode.Open, FileAccess.Read)) { return BitConverter.ToString(algorithm.ComputeHash(fs)).Replace("-", "").ToLowerInvariant(); } } catch (Exception) { throw; } } } static void Main(string[] args) { int totalFiles = 0, processedCount = 0, totalDuplicatesFound = 0; // 替换为实际文件夹路径 string firstPath = @""; string secondPath = @""; DirectoryInfo firstDir = new DirectoryInfo(firstPath); DirectoryInfo secondDir = new DirectoryInfo(secondPath); List<FileInfo> FirstFolderFiles = new List<FileInfo>(); List<FileInfo> SecondFolderFiles = new List<FileInfo>(); Console.WriteLine("Initializing..."); FirstFolderFiles = firstDir.GetFiles("*.*", SearchOption.AllDirectories).ToList(); SecondFolderFiles = secondDir.GetFiles("*.*", SearchOption.AllDirectories).ToList(); // 总任务量为两个文件夹所有文件的哈希计算任务 totalFiles = FirstFolderFiles.Count + SecondFolderFiles.Count; Dictionary<string, List<FileInfo>> secondFolderHashDict = new Dictionary<string, List<FileInfo>>(); Console.WriteLine("Scanning..."); // 先处理第二个文件夹的所有文件,预存哈希 foreach(FileInfo secondFile in SecondFolderFiles) { string hash = ComputeHash(secondFile.FullName); if (!secondFolderHashDict.ContainsKey(hash)) { secondFolderHashDict[hash] = new List<FileInfo>(); } secondFolderHashDict[hash].Add(secondFile); processedCount++; int percentage = processedCount * 100 / totalFiles; Console.WriteLine($"Progress: {percentage} %"); } // 再处理第一个文件夹的文件,直接查字典判断重复 foreach(FileInfo firstFile in FirstFolderFiles) { string hash = ComputeHash(firstFile.FullName); if (secondFolderHashDict.TryGetValue(hash, out var duplicateFiles)) { totalDuplicatesFound += duplicateFiles.Count; } processedCount++; int percentage = processedCount * 100 / totalFiles; Console.WriteLine($"Progress: {percentage} %"); } Console.WriteLine($"Scan completed, total duplicates found: {totalDuplicatesFound}"); } } }
修复后效果
- 时间复杂度从O(M*N)降到O(M+N),文件数量多时性能提升百倍以上
- 进度会随着每个文件的处理线性从0涨到100%,不会出现提前结束、跳变的问题
- 避免了重复计算哈希的冗余操作,执行效率大幅提升
内容的提问来源于stack exchange,提问作者John Smith
相关产品推荐
相关产品推荐

