2015-05-12 169 views
1

使用System.IO.Directory.GetFiles(),我想查找位於NAS服務器上的圖像.png擴展名。Directory.GetFiles()性能問題

string searchingString = "ZLLK9"; 
// original 
var fileList1= Directory.GetFiles(directoryPath).Select(p => new FileInfo(p)).Where(q => q.Name.Substring(0, q.Name.LastIndexOf('.')).Split('_').First() == searchingString); 
// fixed  
var fileList2 = Directory.GetFiles(directoryPath, string.Format("{0}_*.png", searchingString)); 

有兩種方法可以找出包含「ZLLKK9」單詞的文件。

使用LINQ的第一種「原始」方法對於找出文件來說太慢了。 性能問題已經出現,但我不知道「固定」方式有什麼不同?

我需要幫助以便仔細瞭解兩種方式的區別。

+3

您爲什麼認爲這兩種方法之間存在顯着差異? – Tim

+0

如果您試圖找出文件是否包含'.png'擴展名,那麼爲什麼不做一些更容易的操作。 var fi = new DirectoryInfo(directoryPath).GetFiles()。Where(f =>(f.FullName.EndsWith 「.png」)))ToArray();' – MethodMan

回答

3

第一種方式是緩慢的原因有二:

  • 你構建一個FileInfo對象爲每個文件。如果你想要的只是文件名,則不需要這個。構建一個FileInfo是相對較輕的,但它是沒有必要的,如果你查詢了很多文件,所有的實例化會減慢你的速度。既然你真正需要的是文件名,你可以不用這個額外的步驟。

  • LINQ方法檢索所有內容,然後過濾。讓文件系統爲您進行過濾效率更高(更快)。

如果你仍然想使用LINQ,這裏是你的查詢更高性能的版本,這削減了很多枚舉和字符串操作:

var fileList1 = Directory.GetFiles(directoryPath).Where(
    path => Regex.IsMatch(Path.GetFileName(path), @"^ZLLK9_.*\.png$")); 
+0

是的,提問者可以通過將每個'var'放在鼠標上並驗證實際的返回值來驗證。 – AaronLS

+2

由於性能方面的原因,將Directory.GetFiles()提供給文件名模式通常要好得多,而不是像這個答案那樣進行事後過濾。 – reuben

+0

我和你在一起@reuben!我只是解釋了兩種方法之間的差異。 –

4

第一個是獲取該目錄中的所有文件對象,然後執行查詢以查找該名稱。

第二個是隻使用比c#方法(LINQ)快得多的windows內部API返回具有名稱的文件。

性能上的差異更多的是使用比C#代碼更快的內部API。

2

答案就在你使用的方式GetFiles()

您的原始解決方案獲取目錄中的所有文件。然後你的軟件通過它們迭代來找到正確的模式。文檔在這裏:Directory.GetFiles Method (String)

您的固定版本使用不同的.NET Framework方法,即Directory.GetFiles Method (String, String)。第二個參數是搜索模式。在這裏過濾文件不是由您自己編寫的代碼(LINQ),而是由底層操作系統本身進行。

+1

關於你的第二點,我認爲更準確地說,過濾文件是由操作系統本身完成的,而不是由框架完成。 –

+1

@SimonMᶜKenzie:對。發佈更新。 –