2015-04-10 5 views
1

Я нашел много примеров при прохождении через дерево каталогов, но мне нужно что-то немного другое. Мне нужен класс с некоторым методом, который каждый вызов возвращает один файл из каталога и постепенно проходит через дерево каталогов. Как я могу это сделать, пожалуйста? Я использую функции 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)); 
+0

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

+0

Я отредактировал сообщение, надеюсь, он будет более ясным. – zdeniiik

+0

Какую версию VS вы используете? – Scis

ответ

2

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

От 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"; 
    } 
} 

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

EDIT:

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

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

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

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

в основном должны идти через дерево без делать/время, в то время или ... Мне нужен какой-то итератора, который может быть сохранен для последующего использования

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

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

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

+0

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

+0

@SergeBallesta: см. Мое редактирование! –

+0

Переносимость может быть или не быть проблемой (вы правы, это точка для повышения). Но да, производительность также может быть проблемой, или необходимостью наращивать поддержку на нескольких сотнях тысяч компьютеров в средней и большой организации. Существуют случаи, когда boost - это правильный инструмент, а другой - API. –

3

Вот как родной 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 и т.д. Вы можете также передайте его как параметр этой функции, чтобы сделать его более общим.

+0

Нет итератора, требуемого OP. Я все равно дам вам верх, потому что это правильный способ сделать это. Я не совсем уверен, что вы справляетесь с некоторыми более неясными особенностями модели файловой системы Windows правильно ... –

+0

Да, он использует MFC. Спасибо, это может быть решение, но в идеальном случае мне нужен итератор, а не цикл. Но все равно благодарю вас и повысьте. – zdeniiik