Как использовать DirectoryInfo.GetFiles и остановить его после нахождения первого совпадения?

Необходимо выполнить поиск в каталоге/подкаталогах, чтобы найти файл, и предпочел бы, чтобы он остановился, как только он его найдет.

Является ли эта функция встроенной в DirectoryInfo.GetFiles, которую мне не хватает, или я должен использовать что-то еще (самостоятельный рекурсивный поиск)?


person RiddlerDev    schedule 02.02.2012    source источник


Ответы (3)


Вместо этого используйте DirectoryInfo.EnumerateFiles(), который лениво возвращает файлы (в отличие от GetFiles который сначала загружает в память полный список файлов) - вы можете добавить FirstOrDefault() для достижения того, чего хотите:

var firstTextFile = new DirectoryInfo(someDirectory).EnumerateFiles("*.txt")
                                                    .FirstOrDefault();

Из MSDN:

Методы EnumerateFiles и GetFiles различаются следующим образом: при использовании EnumerateFiles можно начать перечисление коллекции объектов FileInfo до того, как вся коллекция будет возвращена; когда вы используете GetFiles, вы должны дождаться возврата всего массива объектов FileInfo, прежде чем вы сможете получить доступ к массиву. Поэтому, когда вы работаете со многими файлами и каталогами, EnumerateFiles может быть более эффективным.

(DirectoryInfo.EnumerateFiles требуется .NET 4.0)

person BrokenGlass    schedule 02.02.2012
comment
Для .NET 3.5 и ниже используйте FindFirstFile(), как показано в моем примере ниже. - person corylulu; 03.02.2012
comment
Для рекурсивного поиска, как упоминалось в теме, просто нужно использовать параметр поиска для метода: EnumerateFiles(*.txt, SearchOption.AllDirectories) - person Vladimir; 27.11.2018

Лучший метод для использования до .NET 4.0 — использовать НайтиПервыйФайл()

    [DllImport("kernel32", CharSet = CharSet.Unicode)]
    public static extern IntPtr FindFirstFile(string lpFileName, out WIN32_FIND_DATA lpFindFileData);

    [DllImport("kernel32.dll", SetLastError = true)]
    public static extern bool FindClose(IntPtr hFindFile);

    public void findFile()
    {
        WIN32_FIND_DATA findData;
        var findHandle = FindFirstFile(@"\\?\" + directory + @"\*", out findData);
        FindClose(findHandle);
    }

Требуется эта структура

    //Struct layout required for FindFirstFile
    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
    struct WIN32_FIND_DATA
    {
        public uint dwFileAttributes;
        public System.Runtime.InteropServices.ComTypes.FILETIME ftCreationTime;
        public System.Runtime.InteropServices.ComTypes.FILETIME ftLastAccessTime;
        public System.Runtime.InteropServices.ComTypes.FILETIME ftLastWriteTime;
        public uint nFileSizeHigh;
        public uint nFileSizeLow;
        public uint dwReserved0;
        public uint dwReserved1;
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260)]
        public string cFileName;
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 14)]
        public string cAlternateFileName;
    }
person corylulu    schedule 02.02.2012
comment
Нужен 4.0, но я также +1 вам за отличный ответ, надеюсь, что это поможет и другим в этом. - person RiddlerDev; 03.02.2012

Вы пробовали DirectoryInfo.GetFiles([Your Pattern], SearchOption.AllDirectories).First();

person Raymund    schedule 02.02.2012