目錄的枚舉經常用到,但是大家大多數用遞歸就能解決問題,但是在某些環境,內存受到限制情況下,遞歸就回佔用大量內存,導致程序崩潰,那麼這個時候怎麼辦?
使用非遞歸!把遞歸轉爲非遞歸
- 目錄的遞歸訪問轉爲非遞歸訪問.以windows 爲例:
- 枚舉目錄需要一個路徑
- 繼續訪問需要上次訪問目錄的句柄
-
- 遇到目錄,將新目錄追加上;保存原來的句柄
-
- 退回上一級,根據\,將目錄退一層;將原來句柄取回來
- 思路就是這樣,代碼呈上:
// enum_dir.cpp : 定義控制檯應用程序的入口點。
//
#include "stdafx.h"
#include <Windows.h>
#include <deque>
#include <string>
std::deque<HANDLE> h_stack;
void push_path(TCHAR* path, const TCHAR* sub_path)
{
while (*path)
{
++path;
}
*path = L'\\';
++path;
while (*sub_path)
{
*path++ = *sub_path++;
}
*path = 0;
}
void pop_path(TCHAR* path)
{
while (*path)
{
++path;
}
path--;
while (*path != _T('\\'))
{
--path;
}
*path = 0;
}
void test(wchar_t* path)
{
WIN32_FIND_DATA d = {};
HANDLE h;
BOOL b = TRUE;
std::wstring str = path;
while (1)
{
//目錄枚舉開始
start:
str = path;
str += L"\\*";
h = FindFirstFile(str.data(), &d);
if (h)
{
while (1)
{
if (!(wcscmp(d.cFileName, L".") == 0 || wcscmp(d.cFileName, L"..") == 0))
{
if (d.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
{
//路徑追加,繼續枚舉
push_path(path, d.cFileName);
//保留句柄,恢復時候使用
h_stack.push_back(h);
//繼續枚舉新目錄
goto start;
}
else
{
//文件
wchar_t buf[512] = {};
wsprintf(buf, L"path:%s:%s\n", path, d.cFileName);
OutputDebugStringW(buf);
}
}
//讀取下一個文件
read_content:
memset(&d, 0, sizeof(d));
b = FindNextFile(h, &d);
if (!b)
{
//這一遭結束,回到上一遭
FindClose(h);
if (h_stack.size())
{
h = *h_stack.rbegin();
h_stack.pop_back();
pop_path(path);
//環境已經恢復繼續枚舉
goto read_content;
}
//否則,game over
goto gameover;
}
}
}
}
gameover:
return;
}
int _tmain(int argc, _TCHAR* argv[])
{
wchar_t buf[260] = { 0 };
wcscpy(buf, L"c:\\test");
test(buf);
return 0;
}
嵌入式中使用fatfs 的時候,也有這樣的情況,可以試一下解決空間佔用問題。