使用C++ MFC进行递归文件搜索?

3
什么是使用C++和MFC递归搜索文件的最干净的方法?
编辑:这些解决方案中有哪些提供使用一个通道进行多个过滤器的能力?我猜想,通过CFileFind,我可以对*.*进行过滤,然后编写自定义代码以进一步将其过滤为不同的文件类型。是否有任何内置的多个过滤器(即*.exe,* .dll)?
编辑2:刚刚意识到我之前做出的一个明显的假设使我的上一个编辑无效了。如果我尝试使用CFileFind进行递归搜索,则必须使用*.*作为通配符,因为否则子目录将无法匹配,也不会发生递归。因此,无论如何都必须单独处理不同文件扩展名的过滤。

2
CFileFind类只是对FindFirstFile和FindNextFile Windows API函数的轻量级封装。这些函数不支持多个通配符。 - Mark Ransom
5个回答

14

使用CFileFind

看一下MSDN上的示例

void Recurse(LPCTSTR pstr)
{
   CFileFind finder;

   // build a string with wildcards
   CString strWildcard(pstr);
   strWildcard += _T("\\*.*");

   // start working for files
   BOOL bWorking = finder.FindFile(strWildcard);

   while (bWorking)
   {
      bWorking = finder.FindNextFile();

      // skip . and .. files; otherwise, we'd
      // recur infinitely!

      if (finder.IsDots())
         continue;

      // if it's a directory, recursively search it

      if (finder.IsDirectory())
      {
         CString str = finder.GetFilePath();
         cout << (LPCTSTR) str << endl;
         Recurse(str);
      }
   }

   finder.Close();
}

4

使用Boost文件系统实现!

递归示例甚至在文件系统主页上:

bool find_file( const path & dir_path,         // in this directory,
                const std::string & file_name, // search for this name,
                path & path_found )            // placing path here if found
{
  if ( !exists( dir_path ) ) return false;
  directory_iterator end_itr; // default construction yields past-the-end
  for ( directory_iterator itr( dir_path );
        itr != end_itr;
        ++itr )
  {
    if ( is_directory(itr->status()) )
    {
      if ( find_file( itr->path(), file_name, path_found ) ) return true;
    }
    else if ( itr->leaf() == file_name ) // see below
    {
      path_found = itr->path();
      return true;
    }
  }
  return false;
}

2

我知道这不是你的问题,但是也可以通过使用 CStringArray 而不使用递归来实现。

void FindFiles(CString srcFolder)
{   
  CStringArray dirs;
  dirs.Add(srcFolder + "\\*.*");

  while(dirs.GetSize() > 0) {
     CString dir = dirs.GetAt(0);
     dirs.RemoveAt(0);

     CFileFind ff;
     BOOL good = ff.FindFile(dir);

     while(good) {
        good = ff.FindNextFile();
        if(!ff.IsDots()) {
          if(!ff.IsDirectory()) {
             //process file
          } else {
             //new directory (and not . or ..)
             dirs.InsertAt(0,nd + "\\*.*");
          }
        }
     }
     ff.Close();
  }
}

哎呀,糟糕了。我不确定能否轻松找到我之前写的代码,但 nd 应该是从 ff.GetFileName()ff.GetFilePath() 中获取的。所以在每次迭代中,您需要将任何找到的目录添加到 dirs 列表中。CFileFind - crashmstr

2

请查看recls库——代表recursive ls,这是一个递归搜索库,可在UNIX和Windows上使用。这是一个C库,可以适应不同的语言,包括C++。从记忆中,您可以按照以下方式使用它:

using recls::search_sequence;


CString dir = "C:\\mydir";
CString patterns = "*.doc;abc*.xls";
CStringArray paths;
search_sequence files(dir, patterns, recls::RECURSIVE);

for(search_sequence::const_iterator b = files.begin(); b != files.end(); b++) {
    paths.Add((*b).c_str());
}

它将在C:\mydir或其任何子目录中查找所有.doc文件和以abc开头的所有.xls文件。我没有编译它,但应该非常接近正确的结果。

-1
CString strNextFileName , strSaveLog= "C:\\mydir";
Find.FindFile(strSaveLog);
BOOL l = Find.FindNextFile();
if(!l)
    MessageBox("");
strNextFileName = Find.GetFileName();

它不起作用。即使文件存在于同一目录中,Find.FindNextFile() 也返回 false。


1
也许你需要在路径中添加通配符?strSaveLog= "C:\mydir\."。另外,在应该放答案的地方不要问问题! - jacobsee

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接