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