尝试读取系统卷信息等的C ++ std :: filesystem :: filesystem_error异常 [英] C++ std::filesystem::filesystem_error exception trying to read system volume information, etc

查看:721
本文介绍了尝试读取系统卷信息等的C ++ std :: filesystem :: filesystem_error异常的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图解决在尝试递归遍历根驱动器中的所有文件(例如C:,D:等)时引发的异常.我在Mingw64上使用GCC编译器版本9.3.0.

I am trying to work around an exception being thrown when trying to recursively walk through all files in root drives, like C:, D:, etc. I am using GCC compiler version 9.3.0 on Mingw64.

尝试读取系统卷信息时出现std :: filesystem :: filesystem_error,示例输出:

I got std::filesystem::filesystem_error when trying to read system volume information, example output:

Checking "D:\\System Volume Information"
filesystem error: cannot increment recursive directory iterator: Invalid argument

代码段:

try {
     for (auto& p : fs::recursive_directory_iterator(dp,  fs::directory_options::skip_permission_denied)) {
            
         cout << "Checking " << p.path() << endl;
         string path = p.path().string();

          if (fs::is_regular_file(p) && p.path().extension() == ".xyz") {
              files.push_back(p.path().string());
          }
      }
}
catch (fs::filesystem_error &e) {
   // How to go back, skip this, and resume?
   cerr << e.what() << endl;
}

我想做的就是跳过这些例外.有人知道怎么做吗?

What I would like to do is skip over these exceptions. Does anyone know how to do that?

谢谢!

推荐答案

由于您的错误涉及到递增recursive_filesystem_iterator,因此该错误似乎来自for语句本身,而不是您的后续代码. for语句在内部对recursive_filesystem_iterator做一个增量(operator++).

Since your error refers to incrementing the recursive_filesystem_iterator, the error appears to be coming from the for statement itself, not your subsequent code. The for statement is internally doing an increment (operator++) on the recursive_filesystem_iterator.

对我来说,这感觉像是实现recursive_filesystem_iterator的错误,并且您的代码应该正常工作.但是,仔细阅读该标准,我想一个实现有足够的歧义,可以说您看到的行为仍然符合该标准.

To me, this feels like an error in the implementation of recursive_filesystem_iterator, and your code should have worked with no exceptions. But reading the standard closely, I suppose there are enough ambiguities for an implementation to say that the behavior you see still conforms to the standard.

我没有c ++ 17标准的正式副本,因此我在此处提供的参考是免费提供的草案

I don't have an official copy of the c++17 standard, so the references I give here are to the freely-available draft n4659.pdf.

30.10.2.1 Posix conformance上说

Implementations that do not support exact POSIX behavior are encouraged to provide
behavior as close to POSIX behavior as is reasonable given the limitations of actual
operating systems and file systems. If an implementation cannot provide any reasonable
behavior, the implementation shall report an error as specified in 30.10.7. [Note:This
allows users to rely on an exception being thrown or an error code being set when an
implementation cannot provide any reasonable behavior.— end note]

Implementations are not required to provide behavior that is not supported by a
particular file system. [Example: The FAT file system used by some memory cards, camera
memory, and floppy disks does not support hard links, symlinks, and many other features
of more capable file systems, so implementations are not required to support those
features on the FAT file system but instead are required to report an error as described
above.— end example]

因此,如果基础文件系统不允许您这样做,则尝试迭代到D:\System Volume Information的尝试可能会失败并引发异常.

So an attempt to iterate into D:\System Volume Information may fail and throw an exception if the underlying filesystem won't let you do that.

您的构造函数指定directory_options::skip_permission_denied.我似乎这足以避免例外.

Your constructor specifies directory_options::skip_permission_denied. I seems like this should be sufficient to avoid the exception.

30.10.14.1 recursive_directory_iterator members中的operator++表示:

...then either directory(*this)->path() is recursively iterated into or, if
    (options() & directory_options::skip_permission_denied) != directory_options::none
and an error occurs indicating that permission to access directory(*this)->path() is denied,
then directory(*this)->path() is treated as an empty directory and no error is reported.

您得到的实际异常不会说权限被拒绝",因此我想可能会争辩说skip_permission_denied选项不适用于它.在这种情况下,这将允许operator++的实现引发异常.我不喜欢这种解释,因为skip_permission_denied的整个想法似乎是避免这样的异常.但这不取决于我. :)

The actual exception that you get doesn't say "permission denied", so I guess it could be argued that the skip_permission_denied option does not apply to it. This would allow the implementation of operator++ to throw an exception in this case. I don't like this interpretation, since it seems like the whole idea of skip_permission_denied is to avoid exceptions like this. But it's not up to me. :)

除了可能尝试将缺陷提交回标准库实现之外,您还能做什么?也许您可以写出旧式的for循环,并在recursive_filesystem_iterator上使用increment方法. increment方法返回错误代码,而不是引发异常.因此您的代码应类似于:

Aside from perhaps trying to submit a defect back to your standard library implementation, what can you do? Perhaps you could write out an old-style for loop, and use the increment method on the recursive_filesystem_iterator. The increment method returns an error code rather than throwing an exception. So your code would look something like:

auto iter = fs::recursive_directory_iterator(dp, fs::directory_options::skip_permission_denied);
auto end_iter = fs::end(iter);
auto ec = std::error_code();
for (; iter != end_iter; iter.increment(ec))
{
    if (ec)
    {
        continue;
    }

    // The rest of your loop code here...
}

我认为以上内容看起来很合理,但绝对需要进行测试,以确保在出现无限循环之类的情况时,不会出现一些奇怪的极端情况.实际上,我不确定甚至不需要continue东西,但您可能想尝试一下.

I think the above looks reasonable, but definitely needs testing to make sure there's not some weird corner case where you get an infinite loop or something. Actually I'm not so sure the continue stuff is even needed, but you may want to experiment with it.

最后,当您抓到filesystem_error时,除了e.what()外,您还可以打印出e.path1.native().我想您已经很了解这些信息了,因为您正在循环中打印路径.但是在某些情况下,它可能会提供更多信息.

Finally, when you catch a filesystem_error, you could print out e.path1.native() in addition to e.what(). I think you already mostly know that information because you're printing the path within your loop. But it might provide more information in some cases.

这篇关于尝试读取系统卷信息等的C ++ std :: filesystem :: filesystem_error异常的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆