2010-12-04 60 views
12

這是一個很長的距離,但有沒有更快的方式來獲取大小,lastaccessedtime,最後創建時間等多個文件?獲得多個FileInfo的更快方法?

我有一個很長的文件路徑列表(所以我不需要枚舉),並且需要儘快查找這些信息。並行創建FileInfo可能無濟於事,因爲瓶頸應該是磁盤。

NTFS日誌只保留不幸的文件名,否則'很棒,我猜操作系統不會在某處存儲元信息?

可能做,如果有一個靜態或Win32調用(文件方法只允許我在同一時間得到一條信息雖然)方法獲取的信息,而這產生了一堆的FileInfo的對象

另外一個優化

不管怎麼說,很高興,如果有人知道的東西,可能會幫助,不幸的是我必須要在這裏做微優化,沒有「使用數據庫」是不是一個可行的答案;)

+0

看看通過NuGet的FluentPath。 http://weblogs.asp.net/bleroy/archive/2010/11/19/fluentpath-1-0.aspx – jvanrhyn 2010-12-04 09:16:43

+0

據我所知,這是一個更好的庫處理文件路徑和linq風格的操作,並沒有與引擎蓋下的文件元數據有很大關係 – Homde 2010-12-04 09:19:09

+0

如果沒有,您是否可以緩存應用程序生命週期開始時的信息?這將在RAM中爲您提供信息,但如果您有長時間運行的應用程序將不會更新。 – Patrick 2010-12-04 09:23:49

回答

8

System.IO.File有靜態方法來得到你想要的。這是一個微型優化,但它可能是你需要的:GetLastAccessTimeGetCreationTime

編輯

我會留下上面的文字,因爲您特別要求使用靜態方法。不過,我認爲你最好使用FileInfo(你應該確定)。 File和FileInfo都使用內部方法File,名爲FillAttributeInfo來獲取您之後的數據。對於您需要的屬性,FileInfo需要調用此方法一次。 File將不得不在每次調用時調用它,因爲方法結束時屬性信息對象被拋棄(因爲它是靜態的)。

所以我的直覺是,當你需要多個屬性時,每個文件的FileInfo會更快。但在表現情況下,您應該始終衡量!面對這個問題,我會嘗試如上所述的兩個託管選項,並在串行和並行運行時都做出基準測試。然後決定它是否足夠快。

如果速度不夠快,則需要直接調用Win32 API。在參考資源中查看File.FileAttributeInfo並且提出類似的內容並不難。

第二編輯

事實上,如果你真的需要它,這是調用Win32 API直接使用相同的方法,內部代號爲File沒有所需的代碼,但使用一個操作系統調用來獲取所有屬性。我認爲你應該只使用它,如果它真的需要。你必須從FILETIME解析到一個可用的日期時間,等等,所以你需要做更多的工作來手動完成。

static class FastFile 
{ 
    private const int MAX_PATH = 260; 
    private const int MAX_ALTERNATE = 14; 

    public static WIN32_FIND_DATA GetFileData(string fileName) 
    { 
     WIN32_FIND_DATA data; 
     IntPtr handle = FindFirstFile(fileName, out data); 
     if (handle == IntPtr.Zero) 
      throw new IOException("FindFirstFile failed"); 
     FindClose(handle); 
     return data; 
    } 

    [DllImport("kernel32")] 
    private static extern IntPtr FindFirstFile(string fileName, out WIN32_FIND_DATA data); 

    [DllImport("kernel32")] 
    private static extern bool FindClose(IntPtr hFindFile); 


    [StructLayout(LayoutKind.Sequential)] 
    public struct FILETIME 
    { 
     public uint dwLowDateTime; 
     public uint dwHighDateTime; 
    } 
    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] 
    public struct WIN32_FIND_DATA 
    { 
     public FileAttributes dwFileAttributes; 
     public FILETIME ftCreationTime; 
     public FILETIME ftLastAccessTime; 
     public FILETIME ftLastWriteTime; 
     public int nFileSizeHigh; 
     public int nFileSizeLow; 
     public int dwReserved0; 
     public int dwReserved1; 
     [MarshalAs(UnmanagedType.ByValTStr, SizeConst = MAX_PATH)] 
     public string cFileName; 
     [MarshalAs(UnmanagedType.ByValTStr, SizeConst = MAX_ALTERNATE)] 
     public string cAlternate; 
    } 
} 
2

是否有可能使用DirectoryInfo類?

DirectoryInfo d = new DirectoryInfo(@"c:\\Temp"); 
FileInfo[] f= d.GetFiles() 
4

.NET的DirectoryInfo中和的FileInfo類是慢得令人難以置信在這個問題上,與網絡共享使用時尤其如此。

如果許多要「掃描」的文件位於同一個目錄中,則通過使用Win32 API的FindFirstFile,FindNextFile和FindClose函數可以獲得更快的結果(取決於具體情況:按維度更快)。如果您需要獲取更多實際需要的信息(例如,如果您要求目錄中的所有「.log」文件,其中只需要其中的75%),則情況更是如此。其實,.NET的info類也在內部使用這些Win32 API函數。但他們只是「刪除」文件名。當要求獲取更多關於一堆文件的信息(例如LastModified)時,每個文件都會有一個單獨的(網絡)請求,這會佔用時間。

0

我認爲你正在尋找GetFileAttributesEx函數(​​)。然而,FileInfo類(或者說,它的基類)在內部使用這個,所以我懷疑你會看到任何性能改進。