Как пройтись по дереву каталогов шаг за шагом?

Я нашел много примеров прохождения по дереву каталогов, но мне нужно что-то немного другое. Мне нужен класс с некоторым методом, который при каждом вызове возвращает один файл из каталога и постепенно проходит по дереву каталогов. Как я могу сделать это, пожалуйста? Я использую функции FindFirstFile, FindNextFile и FindClose, я новичок в C++. У меня есть что-то вроде этого...

Например, у меня есть это простое дерево каталогов

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

и мне нужен класс с методом, например, getNextFile(), этот первый вызов возвращает file1.txt; второй вызов возвращает file2.txt, третий вызов возвращает Child(папку), четвертый вызов возвращает file3.txt и так далее...

Изменить на дубликат флага: мне нужно пройтись по дереву без do/while, while или for... Мне нужен какой-то итератор, который можно сохранить для последующего использования и продолжить с последнего файла, когда я прерываю просмотр, но в идеале только с использованием звонков winapi

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));

2 ответа

Решение

Используйте правильные инструменты. Повышение доступно так же хорошо, как и везде, и имеет методы, которые вы хотите.

С http://rosettacode.org/wiki/Walk_a_directory/Recursively:

#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";
  }
}

удалите весь бизнес регулярных выражений, если вам все равно, соответствует ли ваш файл определенному шаблону.

РЕДАКТИРОВАТЬ:

Не могли бы вы объяснить, почему было бы плохо использовать напрямую вызовы API?

  1. это уродливо и трудно читать, еще труднее понять,
  2. это совсем не портативно, и что самое важное,
  3. Есть миллион угловых случаев, о которых вы должны позаботиться, возможно, при использовании сырого win api. Boost был написан людьми, которые делали это несколько сотен раз и прошли серьезную проверку кода, поэтому выбирайте путь сохранения и не изобретайте колесо заново.

По сути, винапи около двух десятилетий; в остальном мире произошло значительное улучшение юзабилити. Если у вас нет действительно веской причины, я постараюсь абстрагировать как можно больше с помощью общих библиотек, таких как Boost.

Я думаю, что это не решает мою проблему, я отредактировал оригинальный пост, чтобы сделать его более понятным.

в основном нужно пройти по дереву без do/while, while или for... мне нужен какой-то итератор, который можно сохранить для дальнейшего использования

Это именно то, что делает мой ответ: дать вам итератор в цикле for. Я не понимаю, что не соответствует спецификации вашего редактора об этом.

Кроме того, было бы лучше использовать только WinAPI, потому что он должен работать на разных компьютерах с Windows, и установка boost может быть проблемой.

Вам не нужно устанавливать boost на любом из этих компьютеров. Boost::filesystem может быть связан статически; Кроме того, способ старой школы Windows это делает просто boost_filesystem*.dll а также boost_system*.dll вместе с вашим двоичным Однако, если ваша цель - один исполняемый файл, содержащий все необходимые функции, вы все равно будете использовать статическое связывание, так что это абсолютно не проблема.

Вот родной C++ способ сделать это на платформе Windows (с использованием инфраструктуры MFC):

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();
}

Вы можете изменить подстановочную строку для целевых определенных файлов, таких как *.txt и т. Д. Вы также можете передать ее в качестве параметра этой функции, чтобы сделать ее более универсальной.

Другие вопросы по тегам