c#调用api(FindFirstFile,FindNextFile)高效遍历目录文件

在c#下遍历目录,应用最多的应该就是 System.IO.DirectoryInfo.GetDirectories或GetFiles了,但是当目录特别大,文件特别多时,效率不尽人意,此时我们很容易想到三个Win32API函数 FindFirstFile,FindNextFile和FindClose。这三个API搭配使用就能遍历文件和子目录了,而且可以遍历的时候随时中止,避免无谓的操作。在网上搜了一下,发现这方面的文章转载最多的应该就是http://www.cnblogs.com/xdesigner/archive/2006/12/08/586177.html  这篇了,但是按照文中描述的方法,并不能遍历子目录,没办法,就自己想办法,重新写了一个。 

以下为源代码: 

#region 声明WIN32API函数以及结构 **************************************

    [Serializable,

    System.Runtime.InteropServices.StructLayout

      (System.Runtime.InteropServices.LayoutKind.Sequential,

      CharSet = System.Runtime.InteropServices.CharSet.Auto

      ),

    System.Runtime.InteropServices.BestFitMapping(false)]

    private struct WIN32_FIND_DATA

    {

        public int dwFileAttributes;

        public int ftCreationTime_dwLowDateTime;

        public int ftCreationTime_dwHighDateTime;

        public int ftLastAccessTime_dwLowDateTime;

        public int ftLastAccessTime_dwHighDateTime;

        public int ftLastWriteTime_dwLowDateTime;

        public int ftLastWriteTime_dwHighDateTime;

        public int nFileSizeHigh;

        public int nFileSizeLow;

        public int dwReserved0;

        public int dwReserved1;

        [System.Runtime.InteropServices.MarshalAs

          (System.Runtime.InteropServices.UnmanagedType.ByValTStr,

          SizeConst = 260)]

        public string cFileName;

        [System.Runtime.InteropServices.MarshalAs

          (System.Runtime.InteropServices.UnmanagedType.ByValTStr,

          SizeConst = 14)]

        public string cAlternateFileName;

    }

    [System.Runtime.InteropServices.DllImport

      ("kernel32.dll",

      CharSet = System.Runtime.InteropServices.CharSet.Auto,

      SetLastError = true)]

    private static extern IntPtr FindFirstFile(string pFileName, ref WIN32_FIND_DATA pFindFileData);

    [System.Runtime.InteropServices.DllImport

      ("kernel32.dll",

      CharSet = System.Runtime.InteropServices.CharSet.Auto,

      SetLastError = true)]

    private static extern bool FindNextFile(IntPtr hndFindFile, ref WIN32_FIND_DATA lpFindFileData);

    [System.Runtime.InteropServices.DllImport("kernel32.dll", SetLastError = true)]

    private static extern bool FindClose(IntPtr hndFindFile);   

    #endregion



    //具体方法函数



     Stack<string> m_scopes = new Stack<string>();

    private static readonly IntPtr INVALID_HANDLE_VALUE = new IntPtr(-1);

    WIN32_FIND_DATA FindFileData;

    private System.IntPtr hFind = INVALID_HANDLE_VALUE;

    void FindFileInDir(string rootDir)

    {

        string path = rootDir;

        start:

        new FileIOPermission(FileIOPermissionAccess.PathDiscovery, Path.Combine(path, ".")).Demand();

        if (path[path.Length - 1] != '\\')

        {

            path = path + "\\";

        }

        Response.Write("文件夹为:"+path+"<br>");

        hFind = FindFirstFile(Path.Combine(path,"*"), ref FindFileData);

        if(hFind!=INVALID_HANDLE_VALUE)

        {

            do

            {

                if (FindFileData.cFileName.Equals(@".") || FindFileData.cFileName.Equals(@".."))

                    continue;

                if ((FindFileData.dwFileAttributes & 0x10) != 0)

                {

                    m_scopes.Push(Path.Combine(path, FindFileData.cFileName));

                }

                else

                {

                    Response.Write(FindFileData.cFileName+"<br>");

                }

            }

            while (FindNextFile(hFind, ref FindFileData));            

        }

        FindClose(hFind);

        if (m_scopes.Count > 0)

        {

            path = m_scopes.Pop();

            goto start;

        }

    }





//调用方法如下: 



FindFileInDir(@"D:");

 

你可能感兴趣的:(first)