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_DATAAstd::wstringWA

Windows ヘッダーは、定義FindFirstFileされているかのFindFirstFileWようUNICODEに定義されFindFirstFileAます。したがって、一般的な解決策として、typedef astd::basic_string<TCHAR>を文字列型として使用します。そのようにして、 が定義されている場合は std::wstring を使用し、UNICODEそれ以外の場合は std::string を使用します。

于 2012-11-21T00:14:48.353 に答える