简体   繁体   中英

c++ - extract all files names - FindFirstFile

I want to get a list of all files in particular directory.For that |I use the following code

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;
    }
}

In args I transfer a valid existing directory .Actualy args[1] becomes "C:\\dir". But I don`t get a desired list,instead of it the following error occurs :

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

I can`t understand what is wrong here?

You're mixing ANSI with UNICODE and even worse, casting a char* to wchar_t* .

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

If you require your function to use std::string , keep it entirely ANSI (use FindFirstFileA , FindNextFileA and WIN32_FIND_DATAA ). Otherwise work with std::wstring instead and use the functions/structures ending with W instead of A .

The windows headers define FindFirstFile as FindFirstFileW if UNICODE is defined and FindFirstFileA otherwise. So for a generic solution, typedef a std::basic_string<TCHAR> and use that as the string type. That way it uses std::wstring when UNICODE is defined and std::string otherwise.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM