Использование библиотеки <filesystem>; visualStudios - PullRequest
0 голосов
/ 30 мая 2020

Я покончил с этим. Я пытаюсь разобраться в библиотеке файловой системы, но мне удалось найти очень мало информации. Мне удалось заставить его скомпилировать и понять переменную типа filesystem :: path очень хорошо, но, похоже, я не понимаю, как заставить filesystem :: directory_iterator работать должным образом. Я не уверен, что использую его для той цели, для которой он не предназначен. Итак, вот что я пытаюсь сделать:

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

Я могу создать переменную directory_iterator, в которой будет храниться первый файл со мной, просто предоставив ему такой каталог:

const char address[]{ "C:\\Users\\c-jr8\\ProgramBranch\\PersonalPlatform\\log extruder\\logs" };

fs::directory_iterator myIterator(address);

При тестировании кода в папке у меня есть четыре вызываемых текстовых файла «попытка 1» - «попытка 4». При чтении информации о:

https://docs.microsoft.com/en-us/cpp/standard-library/directory-iterator-class?view=vs-2019#op_star

упоминаются две функции для перемещения объекта пути в итераторе к следующему файлу. Первый - это increment (), который является основным методом перебора файлов, и operation ++ ().

Теперь increment () не работает для меня, потому что он принимает переменную типа erro_code, и я не смог найти много информации о том, как реализовать это с помощью переменной filesystem_errorcode или, тем не менее, предназначено для использования. Операция ++ () прекрасно работает и предоставляет мне путь к каждому файлу, но у меня возникли проблемы с управлением кодом, чтобы определить, когда функции operation ++ () не приводят к другим файлам. Как только он перебирает каждый файл, при переходе к следующему происходит своего рода сбой. Вот этот фрагмент кода:

string tempString;
for (int i = 0; i < 5; i++) { //Here the limiting is 5 so it'll iterate onces more than the numbers of files unpurpose to see how it responses.
    tempString = myIterator.operator*().path().generic_string();
    ifstream tempFile(tempString);

    if (!tempFile.is_open()) {
        cout << "Looking at file: " << i + 1 << "; failed to open." << endl << endl;
        cin.get();
        return 0;
    }

    {
        //do things with file...
    }

    tempFile.close();
    myIterator.operator++();
}

Что мне нужно, если я хочу найти способ остановить for l oop, как только итератор отключит последний файл.

любая информация о том, как работает библиотека файловой системы, была бы очень принята.

Ответы [ 2 ]

1 голос
/ 30 мая 2020

std::directory_iterator - это итератор classi c, который позволяет перебирать диапазоны, и они обычно обозначаются парой итераторов, один из которых указывает на начало последовательности, а другой - на прошлое. конечный итератор.

Некоторые типы итераторов, например те, которые предоставляют доступ к потокам, не имеют фактического конечного местоположения в памяти. Аналогичная ситуация применима к итератору каталогов. В таком случае подход idiomati c заключается в использовании сконструированного по умолчанию объекта итератора, который будет служить индикатором конца.

Сказав это, вы можете переписать свой l oop на:

for (fs::directory_iterator myIterator(address), end{}; myIterator != end; ++myIterator) {

В качестве альтернативы вы можете использовать диапазон на основе l oop:

for (auto& p : fs::directory_iterator(address)) {
    tempString = p.path().generic_string();
    // ...

Также обратите внимание, что интерфейс итераторов должен выглядеть / вести себя как указатель, поэтому он использует перегрузку оператора для краткости синтаксиса. Поэтому вместо:

myIterator.operator++();

вы должны использовать:

++myIterator;

Аналогично, вместо:

myIterator.operator*().path().generic_string();

juse используйте:

(*myIterator).path().generic_string();

или:

myIterator->path().generic_string();
1 голос
/ 30 мая 2020

Вы должны сравнить myIterator с построенным по умолчанию directory_iterator, чтобы проверить, был ли обработан последний файл. Вы также можете использовать гораздо более простую форму для доступа к операторам (показано в приведенном ниже коде):

string tempString;

// loop until myIterator == fs::directory_iterator{}
for(size_t i = 1; myIterator != fs::directory_iterator{}; ++i) {

    // access path() through the iterators operator-> 
    tempString = myIterator->path().generic_string();
    ifstream tempFile(tempString);

    if(!tempFile.is_open()) {
        cout << "Looking at file: " << i << "; failed to open." << endl << endl;
        cin.get();
        return 0;
    }
    {
        std::cout << tempString << " opened\n";
    }

    // tempFile.close(); // closes automatically when it goes out of scope

    // simpler form to use myIterator.operator++():
    ++myIterator;
}

Еще более простой подход - использовать для-l oop: * 1006 на основе диапазона *

for(const fs::directory_entry& dirent : fs::directory_iterator(address)) {
    const fs::path& path = dirent.path();
    ifstream tempFile(path);

    if(!tempFile) {
        cout << "Looking at file: " << path << "; failed to open.\n\n";
        cin.get();
        return 0;
    }
    std::cout << path << " opened\n";
}
...