我不想用正確的創建日期創建足夠的文件來做一個體面的基準,所以我做了一個更通用的版本,它需要一個開始和結束時間,並給出匹配的文件的名稱。讓它給出一個特定的昨天創建的文件的子字符串自然就是如此。
我想出了最快的單線程純.NET的回答是:
private static IEnumerable<string> FilesWithinDates(string directory, DateTime minCreated, DateTime maxCreated)
{
foreach(FileInfo fi in new DirectoryInfo(directory).GetFiles())
if(fi.CreationTime >= minCreated && fi.CreationTime <= maxCreated)
yield return fi.Name;
}
我本來期望EnumerateFiles()
要稍微快一點,但事實證明,速度稍慢(可能會怎麼做,如果你最好通過網絡,但我沒有測試)。
有一個輕微的增益:
private static ParallelQuery<string> FilesWithinDates(string directory, DateTime minCreated, DateTime maxCreated)
{
return new DirectoryInfo(directory).GetFiles().AsParallel()
.Where(fi => fi.CreationTime >= minCreated && fi.CreationTime <= maxCreated)
.Select(fi => fi.Name);
}
但不是很多,因爲它不利於實際調用GetFiles()
。如果你沒有使用內核,或者GetFiles()
沒有足夠大的結果,那麼它會讓事情變得更糟(AsParallel()
的開銷大於並行過濾的好處)。另一方面,如果您也可以並行處理下一步的處理過程,那麼總體應用程序速度可能會提高。
對EnumerateFiles()
這樣做似乎沒有意義,因爲它似乎並不是很好並行,因爲它基於我將要使用的相同方法,而且本質上是串行的 - 需要以前的結果來生成下一個。
我得到的最快的是:
public const int MAX_PATH = 260;
public const int MAX_ALTERNATE = 14;
[StructLayoutAttribute(LayoutKind.Sequential)]
public struct FILETIME
{
public uint dwLowDateTime;
public uint dwHighDateTime;
public static implicit operator long(FILETIME ft)
{
return (((long)ft.dwHighDateTime) << 32) | ft.dwLowDateTime;
}
};
[StructLayout(LayoutKind.Sequential, CharSet=CharSet.Unicode)]
public struct WIN32_FIND_DATA
{
public FileAttributes dwFileAttributes;
public FILETIME ftCreationTime;
public FILETIME ftLastAccessTime;
public FILETIME ftLastWriteTime;
public uint nFileSizeHigh;
public uint nFileSizeLow;
public uint dwReserved0;
public uint dwReserved1;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst=MAX_PATH)]
public string cFileName;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst=MAX_ALTERNATE)]
public string cAlternate;
}
[DllImport("kernel32", CharSet=CharSet.Unicode)]
public static extern IntPtr FindFirstFile(string lpFileName, out WIN32_FIND_DATA lpFindFileData);
[DllImport("kernel32", CharSet=CharSet.Unicode)]
public static extern bool FindNextFile(IntPtr hFindFile, out WIN32_FIND_DATA lpFindFileData);
[DllImport("kernel32.dll")]
public static extern bool FindClose(IntPtr hFindFile);
private static IEnumerable<string> FilesWithinDates(string directory, DateTime minCreated, DateTime maxCreated)
{
long startFrom = minCreated.ToFileTimeUtc();
long endAt = maxCreated.ToFileTimeUtc();
WIN32_FIND_DATA findData;
IntPtr findHandle = FindFirstFile(@"\\?\" + directory + @"\*", out findData);
if(findHandle != new IntPtr(-1))
{
do
{
if(
(findData.dwFileAttributes & FileAttributes.Directory) == 0
&&
findData.ftCreationTime >= startFrom
&&
findData.ftCreationTime <= endAt
)
{
yield return findData.cFileName;
}
}
while(FindNextFile(findHandle, out findData));
FindClose(findHandle);
}
}
它冒險不具有FindClose()
由IDisposable
答應了,並IEnumerator<string>
手卷實施不僅應該作出這樣的容易做的(嚴重的理由這樣做),但也希望像3納秒或其他東西(不是一個嚴重的原因),但上面顯示的基本思路。
你可以嘗試使用LINQ。 – Bernard 2012-08-13 19:56:44