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

1 篇文章 0 订阅
1 篇文章 0 订阅
本文介绍了在C#中如何使用Win32 API函数FindFirstFile、FindNextFile和FindClose来高效地遍历大量文件和子目录。相比于System.IO.DirectoryInfo.GetDirectories或GetFiles,这些API提供了更好的性能,并允许在遍历过程中随时停止操作。文章还指出,网上的常见教程存在无法遍历子目录的问题,并提供了作者自己实现的解决方案源代码。
摘要由CSDN通过智能技术生成

在c#下遍历目录,应用最多的应该就是 System.IO.DirectoryInfo.GetDirectories或GetFiles了,但是当目录特别大,文件特别多时,效率不尽人意,此时我们很容易想到三个Win32API函数 FindFirstFile,FindNextFile和FindClose。这三个API搭配使用就能遍历文件和子目录了,而且可以遍历的时候随时中止,避免无谓的操作。在网上搜了一下,发现这方面的文章转载最多的应该就是C#使用WIN32API来高效率的遍历文件和目录 - 袁永福 电子病历,医疗信息化 - 博客园  这篇了,但是按照文中描述的方法,并不能遍历子目录,没办法,就自己想办法,重新写了一个。 

以下为源代码: 



#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:");

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值