【发布时间】:2012-09-27 15:29:33
【问题描述】:
我在 C# 代码中编写了以下算法,以递归方式列出文件夹内的文件。
- 开始遍历目录及其子目录中的文件列表 目录。
- 将文件名和路径存储在列表中。
- 如果当前文件与列表中的任何其他文件匹配,则在 将两个文件标记为重复。
- 从列表中获取所有标记为重复的文件。
- 按名称分组并返回。
在包含 50,000 个文件和 12,000 个子目录的文件夹上执行非常慢。由于磁盘读取操作基本上是耗时的任务。甚至 LINQ.Parallel() 也无济于事。
实施:
class FileTuple { public string FileName { set; get; } public string ContainingFolder { set; get; } public bool HasDuplicate { set; get; } public override bool Equals(object obj) { if (this.FileName == (obj as FileTuple).FileName) return true; return false; } }
- FileTuple 类跟踪文件名和包含目录, 标志跟踪重复状态。
- 我已经重写了 equals 方法来只比较文件名,在 fileTuples 的集合。
以下方法查找重复文件并作为列表返回。
private List<FileTuple> FindDuplicates()
{
List<FileTuple> fileTuples = new List<FileTuple>();
//Read all files from the given path
List<string> enumeratedFiles = Directory.EnumerateFiles(txtFolderPath.Text, "*.*", SearchOption.AllDirectories).Where(str => str.Contains(".exe") || str.Contains(".zip")).AsParallel().ToList();
foreach (string filePath in enumeratedFiles)
{
var name = Path.GetFileName(filePath);
var folder = Path.GetDirectoryName(filePath);
var currentFile = new FileTuple { FileName = name, ContainingFolder = folder, HasDuplicate = false, };
int foundIndex = fileTuples.IndexOf(currentFile);
//mark both files as duplicate, if found in list
//assuming only two duplicate file
if (foundIndex != -1)
{
currentFile.HasDuplicate = true;
fileTuples[foundIndex].HasDuplicate = true;
}
//keep of track of the file navigated
fileTuples.Add(currentFile);
}
List<FileTuple> duplicateFiles = fileTuples.Where(fileTuple => fileTuple.HasDuplicate).Select(fileTuple => fileTuple).OrderBy(fileTuple => fileTuple.FileName).AsParallel().ToList();
return duplicateFiles;
}
您能否提出一种提高性能的方法。
感谢您的帮助。
【问题讨论】:
-
一方面,您的代码无法生成任何匹配项,因为
str.Contains("*.exe")对于所有文件名都是错误的,因为星号。 -
第二,你处于一种命令式的心态。您正在将内容添加到列表等。状态突变不好,无论是顺序代码还是并发代码。相反,您应该对文件名进行分组并查找
Count() > 1所在的组。 -
笔误,已更正,谢谢指出。
-
.Contains(".exe")?来吧,你不应该使用.EndsWith(".exe")吗? -
@Theraot 甚至
Path.GetExtension(filePath)=".exe"。
标签: c#