2012-11-20 52 views
1

我想特別directory.For所有文件的列表|我用下面的代碼C++ - 提取所有文件名 - 用FindFirstFile

void GetFileListing(std::list<std::string>& listing, std::string directory, std::string fileFilter, bool recursively=true) 
{ 


//check if directory exits: 

    DWORD attribs = ::GetFileAttributesA(directory.c_str()); 
    if (attribs == INVALID_FILE_ATTRIBUTES || !(attribs & FILE_ATTRIBUTE_DIRECTORY)) { 
    return ; 
    } 

    // If we are going to recurse over all the subdirectories, first of all 
    // get all the files that are in this directory that match the filter 
    if (recursively) 
    GetFileListing(listing, directory, fileFilter, false); 

    directory += "\\"; 

    WIN32_FIND_DATA FindFileData; 
    HANDLE hFind = INVALID_HANDLE_VALUE; 

    // Setup the filter according to whether we are getting the directories 
    // or just the files 
    std::string filter = directory + (recursively ? "*" : fileFilter); 

    // Find the first file in the directory. 
    hFind = FindFirstFile(LPCWSTR(filter.c_str()), &FindFileData); 

    if (hFind == INVALID_HANDLE_VALUE) 
    { 
    DWORD dwError = GetLastError(); 
    if (dwError!=ERROR_FILE_NOT_FOUND) 
    { 
     std::cout << "Invalid file handle for filter "<<filter<<". Error is " << GetLastError() << std::endl; 
    } 
    } 
    else 
    { 
    // Add the first file found to the list 
    if (!recursively) 
    { 
     wstring wFindFileData = FindFileData.cFileName; 
     listing.push_back(directory + std::string(wFindFileData.begin(),wFindFileData.end())); 
    } 

    // List all the other files in the directory. 
    while (FindNextFile(hFind, &FindFileData) != 0) 
    { 
     if (!recursively) 
     { 
     wstring wFindFileData = FindFileData.cFileName; 
     listing.push_back(directory + std::string(wFindFileData.begin(),wFindFileData.end())); 
     } 
     else 
     { 
     // If we found a directory then recurse into it 
     if ((FindFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)>0 && FindFileData.cFileName[0]!='.') 
     { 
      wstring wFindFileData = FindFileData.cFileName; 
      GetFileListing(listing, directory + std::string(wFindFileData.begin(),wFindFileData.end()), fileFilter); 
     } 
     } 
    } 

    DWORD dwError = GetLastError(); 
    FindClose(hFind); 
    if (dwError != ERROR_NO_MORE_FILES) 
    { 
     std::cout << "FindNextFile error. Error is "<< dwError << std::endl; 
    } 
    } 
} 

int main(int argc, char *argv[]) 
{ 
    if(argc < 2) 
     return 0; 
    std::list<std::string> listing; 
    GetFileListing(listing, argv[1], "*"); 
    for(std::list<std::string>::iterator it = listing.begin(); it!=listing.end();++it) 
    { 
     std::cout << *it << std::endl; 
    } 
} 

在args我傳遞一個有效的現有目錄.Actualy ARGS [1]變成「C:\ dir」。 但我不`噸獲得所需的列表,而不是它會出現以下錯誤:

Invalid file handle for filter C:\dir\*. Error is 123 

我`噸明白什麼是錯在這裏?

+0

您可能想要考慮[直接讀取目錄數據的迭代器](http://stackoverflow.com/q/2531874/179910)。 –

回答

2

您正在將ANSI與UNICODE混合使用,更糟的是,將char*轉換爲wchar_t*

std::string filter; 
// ... 
LPCWSTR(filter.c_str()) // this does not work and causes the error! 

如果你需要你的函數使用std::string,保持它完全ANSI(使用FindFirstFileAFindNextFileAWIN32_FIND_DATAA)。 否則,請與std::wstring一起使用,並使用以W而非A結尾的函數/結構。

如果UNICODE已定義,則窗口標題將FindFirstFile定義爲FindFirstFileW,否則爲FindFirstFileA。因此,對於通用解決方案,鍵入一個std::basic_string<TCHAR>並將其用作字符串類型。這樣,當UNICODE被定義時它使用std :: wstring,否則使用std :: string。

相關問題