之前有個電話面試,其中一道題就是:用非遞歸的方式實現文件夾遍歷?在電面的時候沒有答出來,過后分分鍾就想到了答案,因為之前自己實現過按層序的方式打印一棵樹,用的也是非遞歸的方式,現在遍歷文件夾不就是遍歷這顆樹嗎!怎么就沒想出來呢!在這里簡單的記錄下,用了C#和C++兩個版本實現。
我這里的實現的功能是:用非遞歸的方式獲得一個文件夾中文件的個數。
思路簡單介紹:
1:先將這個文件夾的路徑加入一個隊列中;
2:判斷隊列的元素個數是否大於0,如果元素個數大於0,遍歷第一個元素對應的文件夾,用一個變量fileCounts記錄這個文件夾中文件的個數,如果這個文件夾中有文件夾,就將這個文件夾的路徑加入隊列中,掃描完一個文件夾后,第一個元素彈出隊列,繼續執行第二步,如果隊列中沒有元素,就執行第三步;
3:退出循環
C++版如下:
#include "stdafx.h" #include <Windows.h> #include <iostream> #include <queue> using namespace std; int QueryFileCounts( LPCTSTR Path ) { queue<std::wstring> qFolders; qFolders.push(Path); int fileCounts = 0; WIN32_FIND_DATA findResult; HANDLE handle=NULL; while(qFolders.size()>0) { std::wstring tempFolder = qFolders.front(); tempFolder.append(L"\\*.*"); handle = FindFirstFile(tempFolder.c_str(), &findResult); do { if (findResult.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { if (lstrcmp(L".",findResult.cFileName)==0 || lstrcmp(L"..",findResult.cFileName)==0) { continue; } tempFolder=qFolders.front(); tempFolder.append(L"\\").append(findResult.cFileName); qFolders.push(tempFolder); }else{ fileCounts++; } } while (FindNextFile(handle, &findResult)); qFolders.pop(); } if (handle) { FindClose(handle); handle = NULL; } return fileCounts; } int _tmain(int argc, _TCHAR* argv[]) { { cout<< "文件個數:"<<QueryFileCounts(L"D:\\feinno\\RunImage")<<endl; } system("pause"); return 0; }
運行結果如下:

C#版代碼如下:
using System; using System.Collections.Generic; namespace FileFind { class Program { [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); static int QueryFileCounts( string Path ) { Queue<string> qFolders=new Queue<string>(); qFolders.Enqueue(Path); IntPtr INVALID_HANDLE_VALUE = new IntPtr(-1); int fileCounts = 0; WIN32_FIND_DATA FindFileData=new WIN32_FIND_DATA(); System.IntPtr hFind=INVALID_HANDLE_VALUE; while(qFolders.Count>0) { string floder=qFolders.Dequeue(); string tempFolder = floder; tempFolder+="\\*.*"; hFind = FindFirstFile(tempFolder ,ref FindFileData); if (hFind == INVALID_HANDLE_VALUE) { continue; } do { if ((FindFileData.dwFileAttributes & 0x10) != 0) { if (FindFileData.cFileName.Equals(".") || FindFileData.cFileName.Equals("..")) { continue; } tempFolder=floder+"\\"+FindFileData.cFileName; qFolders.Enqueue(tempFolder); }else{ fileCounts++; } } while (FindNextFile(hFind,ref FindFileData)); } if (hFind != INVALID_HANDLE_VALUE) { FindClose(hFind); } return fileCounts; } static void Main(string[] args) { int count=QueryFileCounts(@"D:\\feinno\\RunImage"); Console.WriteLine("文件個數:" + count ); Console.Read(); } } }
運行結果如下:

