1

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

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 中,我传输了一个有效的现有目录。实际上 args[1] 变为“C:\dir”。但我没有得到想要的列表,而是出现以下错误:

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

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

4

1 回答 1

2

您将 ANSI 与 UNICODE 混合使用,更糟糕的是,将 achar*转换为wchar_t*.

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

如果你要求你的函数使用std::string,请完全保持 ANSI(使用FindFirstFileA,FindNextFileAWIN32_FIND_DATAA)。否则,使用 instead 并使用以instead ofstd::wstring结尾的函数/结构。WA

窗口标题定义FindFirstFileFindFirstFileW如果UNICODE已定义,FindFirstFileA否则。因此,对于通用解决方案, typedef astd::basic_string<TCHAR>并将其用作字符串类型。这样,它在UNICODE定义时使用 std::wstring ,否则使用 std::string 。

于 2012-11-21T00:14:48.353 回答