我写了一个程序,在计算机中查找特定文件,但是在获取计算机上的许多文件时遇到了缓慢和延迟
此功能正在努力获取所有文件
void Get_Files(DirectoryInfo D)
{
FileInfo[] Files;
try
{
Files = D.GetFiles("*.*");
foreach (FileInfo File_Name in Files)
listBox3.Items.Add(File_Name.FullName);
}
catch { }
DirectoryInfo[] Dirs;
try
{
Dirs = D.GetDirectories();
foreach (DirectoryInfo Dir in Dirs)
{
if (!(Dir.ToString().Equals("$RECYCLE.BIN")) && !(Dir.ToString().Equals("System Volume Information")))
Get_Files(Dir);
}
}
catch { }
}
还有另一种方法可以让所有计算机文件更快一点吗?
答案 0 :(得分:2)
使用profiler查找,哪种操作最慢。然后考虑如何让它更快。否则你可以通过优化某些东西来浪费你的时间,这不是瓶颈,也不会带来你预期的加速。
在您的情况下,您可能会发现,当您第一次调用此函数时(当目录结构不在缓存中时),大部分时间将花在GetDirectories()和GetFiles()函数中。您可以预先缓存内存(或数据库)中所有文件的列表,并使用FileSystemWatcher监视文件系统中的更改,以使用新文件更新文件列表。或者您可以使用现有服务,例如Windows索引服务,但这些服务可能并非在每台计算机上都可用。
第二个瓶颈可能是向ListBox添加文件。如果添加的项目数量很大,您可以使用ListBox.BeginUpdate暂时禁用列表框的绘制,完成后,使用ListBox.EndUpdate再次启用它。这有时会导致巨大的加速。
答案 1 :(得分:1)
答案通常取决于您的操作系统。在任何情况下,您都希望构建和维护自己的文件数据库;像你的例子中的显式搜索将太昂贵和缓慢。
Linux上的标准解决方案(以及Mac OS X,如果我没有弄错的话)是维护locatedb文件,系统会定期更新该文件。如果在这些系统上运行,您的程序可以对该数据库进行查询。
答案 2 :(得分:1)
部分问题是,GetFiles方法在获取文件夹中的所有文件之前不会返回,如果您正在执行递归搜索,那么对于您递归的每个子文件夹,它将花费更长时间。
研究使用DirectoryInfo.EnumerateFile或DirectoryInfo.EnumerateFileSystemInfos
来自文档:
EnumerateFiles和GetFiles方法的区别如下:当你 使用EnumerateFiles,您可以开始枚举集合 返回整个集合之前的FileInfo对象;当你使用 GetFiles,你必须等待整个FileInfo对象数组 在您可以访问该数组之前返回。因此,当你是 使用许多文件和目录,EnumerateFiles可以更多 高效。
EnumerateFileSystemInfos
也是如此您还可以查看索引服务(如果已安装并正在运行)。请参阅CodeProject上的这篇文章:
http://www.codeproject.com/Articles/19540/Microsoft-Indexing-Service-How-To
我通过谷歌搜索“如何查询MS文件系统索引”
找到了这个答案 3 :(得分:0)
您可以枚举所有文件一次并存储列表。
但如果你不能这样做,这基本上就像它得到的一样好。你可以做两件小事:
答案 4 :(得分:0)
使用Directory.GetFiles()
可以发现更快的性能,因为FileInfo
和DirectoryInfo
类从文件系统获取额外信息,这比返回基于字符串的文件名要慢得多。
这是一个代码示例,可以产生大大改进的结果,并抽象从列表框中显示文件的操作中检索文件的操作。
static void Main(string[] args)
{
var fileFinder = new FileFinder(@"c:\SomePath");
listBox3.Items.Add(fileFinder.Files);
}
/// <summary>
/// SOLID: This class is responsible for recusing a directory to return the list of files, which are
/// not in an predefined set of folder exclusions.
/// </summary>
internal class FileFinder
{
private readonly string _rootPath;
private List<string> _fileNames;
private readonly IEnumerable<string> _doNotSearchFolders = new[] { "System Volume Information", "$RECYCLE.BIN" };
internal FileFinder(string rootPath)
{
_rootPath = rootPath;
}
internal IEnumerable<string> Files
{
get
{
if (_fileNames == null)
{
_fileNames = new List<string>();
GetFiles(_rootPath);
}
return _fileNames;
}
}
private void GetFiles(string path)
{
_fileNames.AddRange(Directory.GetFiles("*.*"));
foreach (var recursivePath in Directory.GetDirectories(path).Where(_doNotSearchFolders.Contains))
{
GetFiles(recursivePath);
}
}
}