c ++ - 提取所有文件名 - FindFirstFile

时间:2012-11-20 23:27:31

标签: c++ windows file

我想得到特定目录中所有文件的列表。为此|我使用以下代码

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

我不明白这里有什么问题?

1 个答案:

答案 0 :(得分: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

如果定义FindFirstFile,则Windows标头将FindFirstFileW定义为UNICODE,否则定义FindFirstFileA。因此,对于通用解决方案,请键入一个std::basic_string<TCHAR>并将其用作字符串类型。这样它在定义UNICODE时使用std :: wstring,否则使用std :: string。