2012-10-15 151 views
-3

我嘗試編寫查找當前diretory中所有文件及其子目錄的應用程序。我有一個問題,我不能完全理解使用遞歸獲取某個目錄中的所有文件

  1. 我如何需要使用遞歸函數GetFiles()在我的情況,並
  2. ,我需要的是在動態中PathCreator()功能分配的內存。當我測試這個程序僅用於某個目錄(沒有子目錄)時,它可以工作(查看註釋代碼_tmain())。但是,當我試圖讓所有文件崩潰。

這裏是我的代碼:

// ConsoleApplication1.cpp : Defines the entry point for the console application. 
// 

#include "stdafx.h" 
#include <windows.h> 
#include <iostream> 
#define SIZE 300 

int is_directory(wchar_t *p) 
{ 
    wchar_t temp[300]; 
    int i; 
    i = 0; 
    while(*p != '\0') 
    { 
     temp[i] = *p; 
     p++; 
     i++; 
    } 
    temp[i] = '\\'; 
    i++; 
    temp[i] = '\0'; 
    WIN32_FIND_DATA file; 
    HANDLE search_hendle = FindFirstFile(temp, &file); 
    long error = GetLastError(); 
    if(error == 267) 
    { 
     return 0; 
    } 
    else 
    { 
     return 1; 
    } 
} 


wchar_t *PathCreator(wchar_t *dir, wchar_t *fileName) 
{ 
    wchar_t* path = new wchar_t[SIZE]; 
    int j = 0; 
    while(j < SIZE) 
    { 
     path[j] = '\0'; 
     j++; 
    } 
    int i; 
    i = 0; 
    while(*dir != '*' && *dir != '\0') 
    { 
     path[i] = *dir; 
     i++; 
     dir++; 
    } 
    wchar_t *t = fileName; 
    while(*t != '\0') 
    { 
     path[i] = *t; 
     i++; 
     t++; 
    } 
    path[i] = '\0'; 
    return path; 
} 

wchar_t* allFlsArr[SIZE]; 
int i = 0; 
wchar_t **GetAllFiles(wchar_t* dir) 
{ 
    WIN32_FIND_DATA file; 
    HANDLE search_hendle = FindFirstFile(dir, &file); 
    if(search_hendle) 
    { 
     do 
     { 
      wchar_t *p = PathCreator(dir,file.cFileName); 
      allFlsArr[i++] = p; 
     } 
     while(FindNextFile(search_hendle, &file)); 
     allFlsArr[i] = '\0'; 
    } 
    CloseHandle(search_hendle); 
    return allFlsArr; 
} 

void GetFiles(wchar_t *dir) 
{ 
    wchar_t **filePaths = 0; 
    filePaths = GetAllFiles(dir); 
    int i = 0; 
    while(filePaths[i] != '\0'){ 
     if(!is_directory(filePaths[i])) 
     { 
      std::wcout << filePaths[i] << std::endl; 
     } 
     else 
     { 
      GetAllFiles(filePaths[i]); 
     } 
    } 
    delete [] filePaths; 
} 
int _tmain(int argc, _TCHAR* argv[]) 
{ 
    /*wchar_t **wch = GetAllFiles(L"C:\\*"); 
    int i = 0; 
    while(*wch != '\0') 
    { 
     std::wcout << *wch << std::endl; 
     wch++; 
    }*/ 
    GetFiles(L"C:\\*"); 
} 
+0

禁止不必要的代碼很多,(1)你是不是佔 ''和'..',它們都是由您使用的FindXXXX系列函數返回的。你不想枚舉這些。 (2)只要你到達301'st文件,這就是UB。 – WhozCraig

+1

這段代碼有很多問題。看看is_directory的開始。它有一個緩衝區溢出。它泄漏了一個搜索句柄。並且未能檢查FindFirstFile的重試值。手工串工作只是奇怪。 –

+0

@David Heffernan如果這段代碼沒有問題,我就不會在那裏分享它。感謝您的幫助。我已經知道'voila'的語法。 – abilash

回答

2

首先,我不知道爲什麼你從來不使用的功能,如wcscpywcscat或......,總是做所有的字符串,並用手緩衝操作!?但是你身邊有一些問題,在您的代碼:

  • 您使用寬字符串指針的單個陣列(allFlsArr)至GetAllFiles返回結果給調用者,當你迭代導致你會再打電話GetAllFiles這將覆蓋allFlsArr

  • 您正在使用delete[] filePaths解鎖GetAllFiles的結果,但實際上是allFlsArr這是一個全局變量,無法刪除。嘗試std::vector<std::wstring>,不需要delete/new

  • 您的文件名稱數組太小,無法接受文件夾中文件數超過300個文件或文件夾的文件,請再次嘗試std::vector<std::wstring>,該文件的大小可以增加並接受任意數量的項目!

  • 當您使用*搜索文件夾時,Windows返回到您應該從不搜索它們的額外目錄(.,..)。你應該只跳過它們(if(!wcscmp(file.cFileName, L".") || !wcscmp(file.cFileName, L"..")) continue

  • 您使用CloseHandle關閉,從FindFirstFile返回時,你應該使用FindClose手柄。

所以,你可能有這樣的事情:

std::vector<std::wstring> list_files(wchar_t const* folder) 
{ 
    std::wstring root = folder; 
    if(folder.back() == '*') folder.erase(folder.end() - 1); 
    if(folder.back() != '\\') folder.push_back('\\'); 

    std::vector<std::wstring> res; 
    WIN32_FIND_DATA file; 
    HANDLE hSearch = FindFirstFileW(folder, &file); 
    if(hSearch != INVALID_HANDLE_VALUE) { 
     do { 
      if(!wcscmp(file.cFileName, L".") || 
       !wcscmp(file.cFileName, L"..")) 
       continue; 
      res.push_back(root + file.cFileName); 
      if(file.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { 
       // search for sub folders of this folder 
       std::vector<std::wstring> tmp = 
        list_files((root + file.cFileName) + L"\\*"); 
       // all all items to end of our result! 
       res.insert(res.end(), tmp.begin(), tmp.end()); 
      } 
     } while(FindNextFileW(hSearch, &file)); 
     FindClose(hSearch); 
    } 
    return res; 
} 
+0

我知道,使用STL這是任務是更輕鬆,但我怎麼可以用C樸素的方式做到這一點? – abilash

+0

只是更正我提到的錯誤,我的示例使用STL,但糾正錯誤,你仍然可以在沒有STL的情況下工作(例如,用'FindClose'替換'CloseHandle'並返回一個新數組而不是全局數組或類似的東西。 – BigBoss

+0

你是什麼意思「C普通方式」?你的程序是用C++編寫的! –

相關問題