Tôi không cảm thấy muốn tạo đủ tệp với ngày tạo chính xác để làm điểm chuẩn phong nha, vì vậy tôi đã làm một phiên bản tổng quát hơn có thời gian bắt đầu và kết thúc và cung cấp tên tệp phù hợp. Làm cho nó cung cấp cho một chuỗi con cụ thể của các tập tin được tạo ra ngày hôm qua sau tự nhiên từ đó.
Các tinh khiết NET câu trả lời đơn luồng nhanh nhất tôi đã đưa ra là:
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;
}
tôi dự kiến sẽ có EnumerateFiles()
là nhanh hơn một chút, nhưng nó bật ra hơi chậm (có thể làm tốt hơn nếu bạn đi qua một mạng, nhưng tôi đã không kiểm tra điều đó).
Có một tăng nhẹ với:
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);
}
Nhưng không nhiều vì nó không giúp cuộc gọi thực tế để GetFiles()
. Nếu bạn không có lõi để sử dụng, hoặc không có một kết quả đủ lớn từ GetFiles()
sau đó nó sẽ chỉ làm cho mọi thứ tồi tệ hơn (các chi phí của AsParallel()
lớn hơn lợi ích của việc lọc song song).Mặt khác, nếu bạn có thể thực hiện các bước xử lý tiếp theo cũng song song, thì tốc độ ứng dụng tổng thể có thể cải thiện.
Có vẻ như không có điểm nào làm điều này với EnumerateFiles()
vì nó dường như không song song tốt, bởi vì nó dựa trên cùng một cách tiếp cận mà tôi sắp đến, và đó là kết nối trước đó - cần kết quả trước đó để tạo ra kế tiếp.
nhanh nhất tôi nhận được:
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);
}
}
Nó dicey không có mà FindClose()
hứa bởi một IDisposable
và thực hiện cuộn bằng tay của IEnumerator<string>
nên không chỉ làm cho điều đó dễ dàng hơn để làm gì (lý do nghiêm trọng để thực hiện điều đó) nhưng cũng hy vọng cạo đi như 3 nano giây hoặc một cái gì đó (không phải là một lý do nghiêm trọng để làm điều đó), nhưng ở trên cho thấy ý tưởng cơ bản.
Bạn có thể thử sử dụng LINQ. – Bernard