查找文件夹中相同的文件 – C# 实现(原始版)
今日公司一个网络共享盘600G,活生生的被我们塞满到了只剩下300MB,我就在想如何可以从中释放出更多的空间来。共享盘的使用时间有很多年,其中必定有很多文件其实是重复的,被不同的人存了好几份,久而久之就导致了硬盘空间的极度浪费。我们平时在自己电脑中可能也会存在这种文件,特别是mp3啊,图片啊啥么的。
为了解决这个问题,我写了一个简单的小程序来遍历制定的目录,并找出其中相同的两个文件。想法很简单,遍历目录下的所有文件(包含所有子目录),算出遍历到的文件的MD5值,如果有多个文件的MD5值相等就说明这几个文件就是冗余的。说白了这个程序主要就三个主要功能需要实现:遍历目录 + 计算MD5值 + 找到相等后处理。
核心代码如下,利用递归的方法遍历制定目录下的所有文件,并计算哈希值。
/// <summary>< xmlnamespace prefix ="o" ns ="urn:schemas-microsoft-com:office:office" />
/// A Recursive way to traverse all file in the root path
/// </summary>
/// <param name="path">root path need to traverse</param>
/// <param name="level">the max level need to traverse</param>
private void TraverseAll(string path, int level)
{
if (level > maxLevel)
return;
DirectoryInfo curDirInfo = new DirectoryInfo(path);
DirectoryInfo[] childDirs = curDirInfo.GetDirectories();
FileInfo[] childFiles = curDirInfo.GetFiles();
TraverseFiles(childFiles);//此方法遍历所有文件,并记录下重复的
foreach (DirectoryInfo dir in childDirs)
{
TraverseAll(dir.FullName, level + 1);
}
}
/// <summary>
/// Traverse all files pass in, if duplicate record
/// </summary>
/// <param name="files">file list</param>
private void TraverseFiles(FileInfo[] files)
{
foreach (FileInfo f in files)
{
string hashCode = GetFileHashCode(f.FullName);//计算MD5值
try
{
fileTraversed.Add(hashCode, path);
}
catch//如果hashCode已经存在则会抛一个异常
{
if (duplicatedFile.IndexOf(fileTraversed[hashCode].ToString()) < 0)
{
duplicatedFile.Add(fileTraversed[hashCode].ToString());
}
duplicatedFile.Add(path);
}
}
}
完整的Traverse类:http://goo.gl/Og9bX
很愉快的完成了这个功能,但是这个程序的执行速度是蜗牛般的慢,这个我一开始就料到了,只是想写一个实现这个功能。
有以下几点可以改进:
1. 不需要每一个文件都计算MD5值,这个对于大文件太耗时间,可以大概分三层过滤,首先判断文件大小,大小相等计算可以用CRC校验(我不知道这个效率如何)或者可以取文件的几个部分进行校验,如果这步还相等则最后计算MD5值;
2. 计算HashCode对大文件来说是一个很漫长的过程,可以起多个线程来对文件进行计算,这样就会因为一个大文件而让其他没被计算的小文件无法快速计算。(而且现在计算机都是多核的,不用白不用);
3. TraverseFiles这个方法的参数可以通过引用传入,这样如果目录下文件很多的情况下就不用浪费很多内存。
-- The End --