C++中抛出异常后如何继续for循环的下一次迭代?

问题描述 投票:0回答:2

我正在尝试使用

std::filesystem::recursive_directory_iterator
迭代我的 C 驱动器并打印文件路径,但我不断遇到以下异常:
terminate called after throwing an instance of 'std::filesystem::__cxx11::filesystem_error' what():  filesystem error: cannot increment recursive directory iterator: Invalid argument

我已经尝试过:

#include <iostream>
#include <filesystem>

int main() {
    for (auto const& dir_entry : std::filesystem::recursive_directory_iterator("C:\\")) {
        try {
            std::cout << dir_entry << std::endl;
        } catch (std::filesystem::__cxx11::filesystem_error) {
            continue;
        }
    }
    
    return 0;
}

我希望它在遇到异常后继续下一次迭代,但我只是收到了相同的错误消息。

我也尝试过:

#include <iostream>
#include <filesystem>

int main() {
    try {
        for (auto const& dir_entry : std::filesystem::recursive_directory_iterator("C:\\")) {
            std::cout << dir_entry << std::endl;
        }
    } catch (std::filesystem::__cxx11::filesystem_error) {
        std::cout << "Ran into exception";
    }
    
    return 0;
}

它捕获了问题并且执行了

catch
块,但我无法继续下一次迭代,因为
try/catch
语句位于
for
循环之外。

c++ loops error-handling filesystems try-catch
2个回答
0
投票

您无法继续下一个迭代,因为没有下一个迭代。

无法递增递归目录迭代器

如果出现其他异常,您的第一个代码片段可能会工作,但这个代码片段将不允许迭代继续。


0
投票

这是一个解决方法。

#include <iostream>
#include <filesystem>


int main(int argc, char** argv)
{
    if(argc < 1)
        return 1;
    for(std::filesystem::recursive_directory_iterator i {argv[1]}, saved, end;
          i != end; ) {
        const std::filesystem::directory_entry& entry = *i;
        std::cout << entry << '\n';
        /*
         * important: Check symlink first. If it is a symlink and we
         * don't have permission to read it, the is_directory check
         * may throw filesystem_error
         */
        if(! (entry.is_symlink() || entry.is_directory())) { // fast path
            ++i;
            continue;
        }
        saved = i;
        try {
            ++i;
        } catch(std::filesystem::filesystem_error& err) {
            std::cout << "Error: " << err.what() << '\n';
            i = std::move(saved);
            i.disable_recursion_pending();
            ++i;
        }
    }
}

基本上,您可以将迭代器保存在副本中,然后禁用递归。问题在于,这相当昂贵,因为迭代器包含其整个递归状态。所以我们只在必要时复制。

当然更好的选择是设置

skip_permission_denied
标志。但有时您可能想知道是否存在没有权限的目录。那么我认为这是最好的选择。或者,您可以先探测每个目录,而不使用迭代器来查看是否可以读取它,然后根据需要调用
disable_recursion_pending

© www.soinside.com 2019 - 2024. All rights reserved.