简体   繁体   English

在Net 2.0中等效于EnumerateFiles()?

[英]What is the equivalent of EnumerateFiles() in Net 2.0?

I'm processing a large number of files, therefore, I don't want to wait until the whole search is finished before the array is returned. 我正在处理大量文件,因此,我不想等到整个搜索完成后再返回数组。 So I don't want to use Directory.GetFiles() 所以我不想使用Directory.GetFiles()

According to this answer , I need to use EnumerateFiles() in order to get results during the search process. 根据此答案 ,我需要使用EnumerateFiles()才能在搜索过程中获得结果。 However, I'm using NET2.0 and this function seems to be introduced starting from NET 4.0 但是,我使用的是NET2.0,此功能似乎是从NET 4.0开始引入的

What is the equivalent of EnumerateFiles() in Net 2.0 ? 什么是Net 2.0中的EnumerateFiles()?

Any hints would be highly appreciated 任何提示将不胜感激

What you need are the WinAPI calls for FindFirstFile and FindNextFile . 您需要的是WinAPI调用FindFirstFile和FindNextFile Here's some code that uses the wrapped api calls. 这是一些使用包装的api调用的代码。

IEnumerable<string> EnumerateFiles(string path)
{
    APIWrapper.FindData findData = new APIWrapper.FindData();

    APIWrapper.SafeFindHandle handle = APIWrapper.SafeNativeMethods.FindFirstFile(System.IO.Path.Combine(path, "*"), findData);
    if(!handle.IsInvalid && !handle.IsClosed)
    {
        yield return findData.fileName;

        while(!APIWrapper.SafeNativeMethods.FindNextFile(handle, findData))
            yield return findData.fileName;
        handle.Close();
    }
}

I just hand typed EnumerateFiles so treat it as pseudo code, but the class it relies on is production ready, this is it here 我只是手动输入了EnumerateFiles所以将其视为伪代码,但是它依赖的类已经可以生产了,就在这里

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

Specially added as a new answer.. 特别添加为新答案。

Since .NET 2.0 There is IENumerable and yield keyword does Lazy Initialization/deferred execution..With these, you can get your wants. 从.NET 2.0开始,有IENumerable和yield关键字进行延迟初始化/延迟执行。有了这些,您就可以得到想要的。

public IEnumerable<string> GetFiles(string rootPath, string [] fileNameStartChars, string[] extensionsFilter)
        {
            FileSystemInfo[] fsi = null;
            for(int i = 0; i < fileNameStartChars.Length; i++)
            {
                for(int k = 0; k<extensionsFilter.Length; k++)
                {
                    fsi = new DirectoryInfo(rootPath).GetFileSystemInfos(fileNameStartChars[i]+extensionsFilter[k]);

                    if (fsi.Length > 0)
                    {
                        for (int j = 0; j < fsi.Length; j++)
                        {

                          /// .Name returns the filename with extension..if you need, please implement here a substring for eliminate the extension of the file
                            yield return fsi[j].Name;
                        }
                    }
                }

            }

        }

And usage : 和用法:

possible filenames startsWithChar table 可能的文件名startsWithChar表

public string[] table = new string[]
        {
          "A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z",
          "a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q","r","s","t","u","v","w","x","y","z",
          "1","2","3","4","5","6","7","8","9","0","#","_","-",".","@","+",",","%","&","(",")","[","]","{","}","*",
          "<",">","^"," ","|",";","`"
         };

And extensions : 和扩展名:

string[] Exts = new string[] { ".mp3", ".midi", ".wav"};

with this method, you can filter your data within small parts as such as using startswithchar filtering, so you won't get Memory problem which depends to your files count..This is the tricky part of trying to imitate .net v4's EnumerateFiles method with 100% .net v2 managed code.. 使用此方法,您可以在较小的部分中过滤数据,例如使用startswithchar过滤,因此不会出现取决于文件数量的内存问题。这是尝试模仿.net v4的EnumerateFiles方法的棘手部分100%.net v2托管代码..

     IEnumerable<string> strNumerable = GetFiles(@"D:\Music", table, Exts);


///Since its deferred execution, method didn't get any memory alloc for your data till now..Memory Alloc will start within this foreach..

            foreach (string s in strNumerable)
            {
               //do your work
            }

Since .NET 2.0 There is IENumerable and yield keyword does Lazy Initialization ..With these, you can get your wants. 从.NET 2.0开始,有IENumerableyield关键字会进行Lazy Initialization ..有了这些,您就可以得到想要的。

With a pseudo : 用伪:

public IENumerable GetFiles(string Path, string FileExtension)
{
   // Create a new IENumerable instance
   // Get FileCount with DirectoryInfo or some similar
   // Implement a for-loop with File count
   // If DirectoryFiles [ indexOfForLoop ] .Extension == FileExtension

   yield return DirectoryFiles [indexOfForLoop ]
}

In this pseudo the yield keyword take responsibility of the filtering..If filtering returns true the yield return immediately return the result to the IENumerable instance / callee.. 在此伪IENumerableyield关键字负责过滤。如果过滤返回true,则yield return立即将结果返回到IENumerable实例/被调用者。

And IEnumerable takes responsibility of Lazy Loading.. IEnumerable负责延迟加载。

Depends to your needs, Also you can use yield break keyword in loop to not include the result.. 根据您的需要,也可以在循环中使用yield break关键字不包含结果。

And with a simple call : 并通过一个简单的电话:

List<string> FilesInDirectory = GetFiles( path, "*.txt").ToList();

Hope this helps.. 希望这可以帮助..

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM