C # получить имена файлов и время последней записи для больших каталогов - PullRequest
2 голосов
/ 16 ноября 2009

Используя C # (.NET 2.0), каков наилучший способ получения списка файлов в сетевом каталоге с предпочтением либо сортировки по времени последней записи, либо исключения возврата на основе времени последней записи?

В настоящее время я возвращаю список, используя метод GetFiles экземпляра DirectoryInfo. Каталоги, с которыми я сталкиваюсь, могут содержать более 6000 файлов, и только для того, чтобы вернуть массив FileInfo, требуется почти 25 секунд.

WMI не будет работать, и я не вижу ничего другого, ориентированного на .NET, которое поможет в этой ситуации. Я что-то пропустил? Есть ли лучшее решение, чем использовать GetFiles?

Спасибо.

Ответы [ 2 ]

7 голосов
/ 16 ноября 2009

Обновление
Я только что заметил этот старый ответ, для .net 4.0 и более поздних версий есть метод System.IO.EnumerateFiles, который делает это для вас, для всего до .net 4.0, читайте дальше.

.Net 3.5 и ранее

Я со Стефаном, я столкнулся с этой проблемой и развернул свой собственный перечислитель, чтобы перебирать папки с файлами + 100k.

Этот класс охватывает все специфичные для API вещи, которые вам понадобятся для использования FindFirstFile и FindNextFile.

Надеюсь, это поможет,

internal class APIWrapper
{
    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
    internal sealed class FILETIME
    {
        public int Low;
        public int High;
        public Int64 ToInt64()
        {
            Int64 h = High;

            h = h << 32;
            return h + Low;
        }
    }


    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
    internal sealed class FindData
    {
        public int fileAttributes;
        public FILETIME CreationTime;
        public FILETIME LastAccessTime;
        public FILETIME LastWriteTime;
        public int FileSizeHigh;
        public int FileSizeLow;
        public int dwReserved0;
        public int dwReserved1;
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260)]
        public String fileName;
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 14)]
        public String alternateFileName;
    }
    internal sealed class SafeFindHandle : Microsoft.Win32.SafeHandles.SafeHandleMinusOneIsInvalid
    {
        /// <summary>
        /// Constructor
        /// </summary>
        public SafeFindHandle()
            : base(true)
        {
        }

        /// <summary>
        /// Release the find handle
        /// </summary>
        /// <returns>true if the handle was released</returns>
        [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
        protected override bool ReleaseHandle()
        {
            return SafeNativeMethods.FindClose(handle);
        }
    }

    internal enum SearchOptions
    {
        NameMatch,
        LimitToDirectories,
        LimitToDevices
    }
    [SecurityPermissionAttribute(SecurityAction.Assert, UnmanagedCode = true)]
    internal static class SafeNativeMethods
    {
        [DllImport("Kernel32.dll", CharSet = CharSet.Auto)]
        public static extern SafeFindHandle FindFirstFile(String fileName, [In, Out] FindData findFileData);

        [DllImport("Kernel32.dll", CharSet = CharSet.Auto)]
        public static extern SafeFindHandle FindFirstFileEx(
            String fileName,                    //__in        LPCTSTR lpFileName,
            [In] int infoLevel,                 //__in        FINDEX_INFO_LEVELS fInfoLevelId,
            [In, Out] FindData findFileData,    //__out       LPVOID lpFindFileData,
            [In, Out] SearchOptions SerchOps,             //__in        FINDEX_SEARCH_OPS fSearchOp,
            [In] int SearchFilter,              //__reserved  LPVOID lpSearchFilter,
            [In] int AdditionalFlags);          //__in        DWORD dwAdditionalFlags

        [DllImport("kernel32", CharSet = CharSet.Auto)]
        [return: MarshalAs(UnmanagedType.Bool)]
        public static extern bool FindNextFile(SafeFindHandle hFindFile, [In, Out] FindData lpFindFileData);

        [DllImport("kernel32", CharSet = CharSet.Auto)]
        [return: MarshalAs(UnmanagedType.Bool)]
        public static extern bool FindClose(IntPtr hFindFile);
    }
}
2 голосов
/ 16 ноября 2009

Проблема не в сопоставлении экземпляров FileInfo, а в вызове API, который выполняется при обращении к последнему времени записи.

Чтобы получить значительно более быстрый ответ, вам нужно самостоятельно вызвать функции Win32 API FindFirstFile и FindNextFile.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...