How to walk through directory tree step by step?

我只是一个虾纸丫 提交于 2020-01-13 05:49:07

问题


I found many examples on walking through directory tree, but I need something a little different. I need a class with some method which each call returns one file from directory and gradually walking through directory tree. How can I do this please? I am using functions FindFirstFile, FindNextFile and FindClose, I am newbie in c++. I have something like this...

For example I have this simple directory tree

Parent(folder)\
   file1.txt
   file2.txt
   Child(folder)\
       file3.txt
       file4.txt

and I need a class with a method for example getNextFile(), that first call returns file1.txt; second call returns file2.txt, third call returns Child(folder), fourth call returns file3.txt and so on...

Edit on duplicate flag: I basically need walk through tree without do/while, while or for...I need some kind of iterator, which can be stored for later use and which can continue from last file, when I interrupt browsing, but ideally only with using winapi calls

WIN32_FIND_DATA fdFile;
HANDLE hFind = NULL;
if((hFind = FindFirstFile(sPath, &fdFile)) == INVALID_HANDLE_VALUE)
{
    return false;
}
do
{
    //do some job with fdFile
}
while(FindNextFile(hFind, &fdFile));

回答1:


Use the right tools. Boost is available as good as everywhere, and has the methods you want.

From http://rosettacode.org/wiki/Walk_a_directory/Recursively#C.2B.2B:

#include "boost/filesystem.hpp"
#include "boost/regex.hpp"
#include <iostream>

using namespace boost::filesystem;

int main()
{
  path current_dir("."); //
  boost::regex pattern("a.*"); // list all files starting with a
  for (recursive_directory_iterator iter(current_dir), end;
       iter != end;
       ++iter)
  {
    std::string name = iter->path().filename().string();
    if (regex_match(name, pattern))
      std::cout << iter->path() << "\n";
  }
}

remove the whole regex business if you don't care whether your file matches a certain pattern.

EDIT:

Could you please explain why it would be bad to use directly API calls ?

  1. it's ugly and hard to read, even harder to get right,
  2. it's not portable at all, and what's most important,
  3. there's a million corner cases you'd have to take care of, possibly, when using the raw win api. Boost has been written by people who did this a few hundred times and has underwent serious code review, so take the save route, and don't reinvent a wheel.

In essence, winapi is about two decades old; there's been a lot of usability improvement in the rest of the world. Unless you have a really good reason, I would try to abstract as much of it away as possible by using common libraries, such as Boost.

I think this does not solves my problem, I edited the original post to make it clearer.

basically need walk through tree without do/while, while or for...I need some kind of iterator, which can be stored for later use

That's exactly what my answer does: give you an Iterator in a for loop. I don't understand what's not fulfilling your Edit's specification about that.

In addition, it would be best to use only WinAPI, because it has to work on different computers with windows and installing boost could be a problem.

You don't have to install boost on any of these computers. Boost::filesystem can comfortable be linked in statically; also, the old-school windows way of doing this is just delivering boost_filesystem*.dll and boost_system*.dll along with your binary. However, if your goal is a single executable that contains all needed functions, you'll go for static linkage, anyway, so this is absolutely no problem.




回答2:


Here is the native C++ way of doing it on Windows platform (using MFC framework):

void ListFiles(const CString& sPath)
{
   CFileFind finder;

   CString sWildcard(sPath);
   sWildcard += _T("\\*.*");

   BOOL bWorking = finder.FindFile(sWildcard);

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

      if (finder.IsDots())
         continue;

      if (finder.IsDirectory())
      {
         CString sFilePath = finder.GetFilePath();
         // TODO: do stuff here
         ListFiles(sFilePath);
      }
   }

   finder.Close();
}

You can change wild card string to target specific files, like *.txt etc. You can also pass it as a parameter to this function to make it more general purpose.



来源:https://stackoverflow.com/questions/29556174/how-to-walk-through-directory-tree-step-by-step

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!