2012-04-13 65 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文件系統索引」