2012-04-13 28 views
2

我写了一个程序寻找计算机中的特定文件,但是从慢遭受从获得计算机如何使文件的节目搜索快速

此功能工作,在许多文件延迟获取所有文件

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 { } 
     } 

是否有另一种方法可以让所有计算机文件快一点?

+1

可能创建索引 – chepe263 2012-04-13 21:25:11

+5

当我看到catch {}时,我收到了一次扣押。 – usr 2012-04-13 21:25:50

+0

搜索整个计算机将需要很长时间。 如果应用二分搜索算法,则可以加快速度。文件按字母顺序排序,检查中间文件,看看你应该看看该文件之前还是之后,然后再检查中间。 – MrFox 2012-04-13 21:28:01

回答

2

使用Profiler来看看,什么操作是最慢的。然后想想如何让它更快。否则,你可以通过优化某些东西来浪费时间,这不是瓶颈,也不会带给你预期的加速。在您的情况下,您可能会发现,当您第一次调用此函数时(目录结构不在缓存中时),大部分时间将花在GetDirectories()和GetFiles()函数中。您可以预先缓存内存(或数据库)中的所有文件的列表,并使用FileSystemWatcher监视文件系统中的更改以使用新文件更新文件列表。或者您可以使用现有服务,例如Windows索引服务,但这些服务可能不适用于每台计算机。

第二个瓶颈可能是将文件添加到ListBox。如果添加的项目数量很大,则可以使用ListBox.BeginUpdate临时禁用列表框的绘制,当完成时,请使用ListBox.EndUpdate再次启用它。这有时会导致巨大的加速。

+0

好,我该如何利用程序中的索引服务C# – 2012-04-13 22:19:47

+0

微软有SDK,其中包括C#中的示例代码。看[这里](http://msdn.microsoft.com/en-us/library/windows/desktop/bb266517(v = vs.85).aspx) – 2012-04-13 22:36:54

1

答案一般取决于您的操作系统。无论如何,你会想要建立和维护你自己的文件数据库;在你的例子中进行明确的搜索将会过于昂贵和缓慢。

在Linux(和Mac OS X,如果我没有弄错的话)上的标准解决方案是维护一个locatedb文件,该文件由系统定期更新。如果在这些系统上运行,你的程序可以对这个数据库进行查询。

+0

我的搜索程序不是在寻找数据库,但为图像文件和文本? – 2012-04-13 21:28:43

+0

数据库将包含您感兴趣的文件的路径。请参阅我的答案中的链接以获取更多详细信息。 – 2012-04-13 21:30:52

+0

那么,如何在程序中使用数据库呢? – 2012-04-13 21:47:29

0

您可以枚举一次所有文件并存储列表。

但是,如果你不能这样做,这基本上是一样好。你可以做两件小事:

  • 尝试使用线程。这将在固态硬盘上变得更好,但可能会损坏旋转磁盘
  • 使用DirectoryInfo.GetFileSystemEntries。这将通过一个有效的调用返回文件和目录。
0

你会发现使用Directory.GetFiles()FileInfoDirectoryInfo类更快的性能得到了文件系统,这是比简单地比返回基于字符串的文件名慢得多的额外信息。

这里是一个代码示例应产生显着改善结果,并从抽象在列表框中显示它们的操作检索文件的作用。问题的

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); 
     } 
    } 
} 
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文件系统索引”