利用 <filesystem> 库;视觉工作室

Utilizing the <filesystem> library; visualStudios

我会缩短它的长度。我试图了解文件系统库,但我能找到的信息很少。我设法让它编译并很好地理解 filesystem::path 类型变量,但似乎不明白如何让 filesystem::directory_iterator 正常工作。我不确定我是否将它用于非设计目的。所以这就是我正在尝试做的事情:

我想创建一个程序来打开指定文件夹中的每个文本文件。为此,我需要获取文件夹名称和路径,但我希望程序能够自行动态获取此信息,因此如果我添加或删除 textFiles,它将具有正常运行的逻辑。

我能够创建一个 directory_iterator 变量,它设法保存第一个文件,只需给它这样的目录:

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

fs::directory_iterator myIterator(address);

测试文件夹中的代码时,我有四个名为 "attempt 1" 到 "attempt 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++() 工作得很好,并为我提供了每个文件的路径,但我在管理代码以检测 operate++() 函数何时导致没有其他文件时遇到了问题。一旦遍历每个文件,当它继续移动到下一个文件时,它就会崩溃。这是那段代码:

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 循环。

任何有关文件系统库如何工作的信息都将不胜感激。

您应该将 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;
}

一种更简单的方法是使用基于范围的 for 循环:

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

std::directory_iterator 是一个经典的迭代器,它允许在范围内进行迭代,这些迭代器通常由一对迭代器指定,一个表示序列的开始,另一个表示尾后迭代器。

一些迭代器类型,如提供流访问的迭代器类型,在内存中没有实际的结束位置。类似的情况适用于目录迭代器。在这种情况下,惯用的方法是使用默认构造的迭代器对象作为结束指示器。

话虽如此,您可以将循环重写为:

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

或者,您可以使用基于范围的 for 循环:

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

此外,请注意迭代器的 接口 应该像指针一样 look/behave,因此它使用运算符重载以实现简洁的语法。所以而不是:

myIterator.operator++();

你应该使用:

++myIterator;

同样,代替:

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

请使用:

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

或:

myIterator->path().generic_string();