以深度優先方式作 recursive file scan
#define _CRT_SECURE_NO_WARNINGS #include <ctype.h> #include <io.h> #include <stdio.h> #include <math.h> #include <conio.h> #include <stdlib.h> #include <iostream> using namespace std; //串接路徑 dir 與後續名稱 name, 存入 out void path_cat (char* out, char* dir, char* name) { int i = strlen (dir); char ch = dir[i-1]; strcpy (out, dir); if (ch!='/' && ch!='\\') { //尾端需要補'/'嗎? out[i] = '/'; out[++i] = '\0'; } strcpy (out+i, name); } template <class TClass> struct ScanDir { typedef void (TClass::*PFT)(); //Type of member function pointer TClass* obj; //pointer to processing object PFT process_enter; PFT process_each_scan; enum {MAX_LEVEL = 16}; //進行掃描時的最大遞迴層數 char** path; //每層的暫存路徑 int curLevel; //目前掃描到的層數 int nSubDir; //目前掃描到的層, 當中的子目錄個數 _finddata_t* curFile; //目前掃描到的檔案資訊 char* curDir; //目前掃描到的目錄名稱 int nFilter; //欲處理的副檔名數目, 最多 32 筆 char filter[32][8]; //欲處理的副檔名集合, 最多 32 筆 ScanDir() { path = (char**) new_arr (sizeof(char), 2, MAX_LEVEL, 256); } ~ScanDir() { del_arr (path); } // 裝載搜索資訊 // sFilter = 欲處理的副檔名集合, 以.分隔與結束, 如: "html.flash." void setup (TClass* ref, PFT enter, PFT scan, char* sFilter=0) { obj = ref; process_enter = enter; process_each_scan = scan; nFilter = 0; if (sFilter) for (char* p=sFilter; *p; ++p) if (*p == '.') { strncpy (filter[nFilter], sFilter, p-sFilter); filter [nFilter][p-sFilter] = '\0'; nFilter++; sFilter = p+1; } } bool match_filter () //過濾副檔名 { //若副檔名存在 filter int i; //集合中則回傳 true char* s = curFile->name; char* p = s + strlen (s) - 1; for (i=0 ;p>s && i<8; ++i, --p) if (*p == '.') {p++; break;} if (i > 0) //副檔名至少要有一個字元 for (i=0; i<nFilter; ++i) if (strcmp (p, filter[i]) == 0) return true; return false; } void scan (char* dir, int level=0) //dir 必須是目錄名稱 { char* s = path[level]; path_cat (s, dir, "*.*"); _finddata_t file; long hFile = _findfirst (s, &file); if (hFile == -1) { puts ("No files in current directory"); return; } curDir = dir; curLevel = level; //紀錄目前掃描到的層數 nSubDir = 0; //計算當前目錄中 do if ((file.attrib & _A_SUBDIR) && //子目錄的個數 strcmp (file.name, ".") != 0 && strcmp (file.name,"..") != 0) //若 nSubDir = 0 nSubDir++; //表示已掃描到葉節點 while (_findnext (hFile, &file) == 0); _findclose (hFile); (obj->*process_enter)(); //執行進入目錄時的 //前置處理 hFile = _findfirst (s, &file); do { if (file.attrib & _A_SUBDIR) { //若是目錄 if (strcmp (file.name, ".") != 0 && strcmp (file.name,"..") != 0) { path_cat (s, dir, file.name); scan (s, level+1); } } else { curFile = &file; if (nFilter && match_filter()) //對符合過濾條件的 (obj->*process_each_scan)(); //檔案進行特定處理 } } while (_findnext (hFile, &file) == 0); _findclose (hFile); } };
測試程式:
struct Test { int n; ScanDir<Test> scan_dir; void in_each_scan () { _finddata_t* f = scan_dir.curFile; char* type = (f->attrib & _A_SUBDIR)? "目錄":"檔案"; printf("\nLevel: %2d, [%3d] %s %s", scan_dir.curLevel, n++, type, f->name); getch(); } void at_enter () { printf ("\n------------ %s -------------", scan_dir.curDir); } void scan (char* path) { if (_access (path,0) != 0) { printf ("%s 目錄不存在!", path); getch(); return; } n = 0; scan_dir.setup (this, &Test::at_enter, &Test::in_each_scan, "jpg.bmp.png.gif.jpeg."); scan_dir.scan (path); } }; int main() { char path[512] = "../../image/DM/" ; Test test; test.scan (path); return getch(); }
沒有留言:
張貼留言