Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use DirectoryInfo.GetFiles and have it stop after finding the first match?

Need to search the directory/sub-directories to find a file, would prefer it to stop once it has found one.

Is this a feature built into DirectoryInfo.GetFiles that I am missing, or should I be using something else (self-implemented recursive search)?

like image 410
RiddlerDev Avatar asked Dec 03 '22 05:12

RiddlerDev


2 Answers

Use DirectoryInfo.EnumerateFiles() instead which is lazily returning the files (as opposed to GetFiles which is bringing the full file list into memory first) - you can add FirstOrDefault() to achieve what you want:

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

From MSDN:

The EnumerateFiles and GetFiles methods differ as follows: When you use EnumerateFiles, you can start enumerating the collection of FileInfo objects before the whole collection is returned; when you use GetFiles, you must wait for the whole array of FileInfo objects to be returned before you can access the array. Therefore, when you are working with many files and directories, EnumerateFiles can be more efficient.

(DirectoryInfo.EnumerateFiles requires .NET 4.0)

like image 87
BrokenGlass Avatar answered Dec 06 '22 10:12

BrokenGlass


The best method to use for pre-.NET 4.0, use FindFirstFile()

    [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);
    }

Requires this struct

    //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;
    }
like image 20
corylulu Avatar answered Dec 06 '22 10:12

corylulu