2007/12/25

KB-程式存取大量檔案資料夾的注意事項

最近遇到一個  case ,有一個資料夾中有超過10萬個檔案,記得檔案總管要開啟一個資料夾中含有 2 萬個檔案時,就已經無法回應,更別說排序了。

以前比較常的解決方案是從 DB 取得檔名後,直接 MOVE 檔案。

但是…如果沒有留存一份在 DB 呢?

.net 中有一個 System.IO.Directory 物件,有一個 Method 叫做 GetFiles ,可以回傳 Files 的 String Array ,

看來是很好用,不過,面臨到超過10萬個檔案的資料夾,在還沒有將 String Array 回傳時,應該就會將記憶體吃到滿載,

還可能會被 .net CLR 認為是一個發狂吃記憶體的豬頭程式,另外速度之慢,去吃一頓飯回來還不見得跑得出來。

看了一下 MSDN 中高手 Stephen Toub 的 NETMatter 專欄,有一段寫到 Directory.GetFiles 的問題與解決方式(註一)

主要是改用 Windows API 中的 FindFirstFile() 取得目錄中的第一個檔案後,再呼叫 FindNextFile() 遞迴存取檔案。

在這個專欄中,也有範例程式可以下載(註二)

實際使用後發現速度飛快,1000倍的差距一點都不誇張 (Y)。

改寫也蠻快的,由於 Stephen 了一個 FileSearcher Class ,首先很完整的 copy 至我的專案,

將原本的 Directory.GetFiles 一行打死的動作,改為 Foreach + FileSearcher.GetFiles 即可。

case 就這樣子透用 Stephen 的幫忙,很快就可以 Close ,不過裡面有很多可以再追根究抵的,例如:

SafeFindHandler , C# iterator performance (註三) .... 有空再研究囉~(掩面哭逃)

 

註一:http://msdn.microsoft.com/msdnmag/issues/05/12/NETMatters/

註二:http://download.microsoft.com/download/2/e/9/2e9bde04-3af1-4814-9f1e-733f732369a3/NETMatters0512.exe

註三:Recursive iterator performance , Recursive iterator performance, part 2 , Recursive iterator performance, part 3

 

沒有留言: