


Почему в C++ 20, filesystem::exists кидает исключение если попытаться проверить наличия папки на несуществующем диске
и как это исправить
просто надо отлавливать исключения и нет проблем
Используйте безопасный вариант, который возвращает ошибку
bool exists(const path& pval, error_code& ec) noexcept;
Исключения нужно ловить это очень очень полезно.
В C++20 функция `std::filesystem::exists` может выбрасывать исключение, если вы пытаетесь проверить наличие папки на несуществующем диске. Это происходит из-за того, что система возвращает ошибку, связанную с недоступностью пути, например, `ERROR_BAD_NETPATH`, и эта ошибка не всегда мапируется на "файл не найден" или "нет такого файла или директории" в стандартной библиотеке C++[1][6].
Чтобы исправить эту проблему, можно использовать несколько подходов:
1. Обработка исключений: Оберните вызов `std::filesystem::exists` в блок `try-catch` и обрабатывайте исключение `std::filesystem::filesystem_error`, чтобы корректно реагировать на ошибки, связанные с недоступными дисками или путями[5][7].
```cpp
#include <iostream>
#include <filesystem>
namespace fs = std::filesystem;
int main() {
fs::path path = "Z:\\nonexistent_folder";
try {
if (fs::exists(path)) {
std::cout << "Папка существует.\n";
} else {
std::cout << "Папка не существует.\n";
}
} catch (const fs::filesystem_error& e) {
std::cerr << "Ошибка: " << e.what() << '\n';
}
return 0;
}
```
2. Использование версий функций без генерации исключений: Некоторые функции в `std::filesystem` имеют версии, которые не выбрасывают исключения. Вместо этого они возвращают логическое значение и заполняют объект `std::error_code`, который можно использовать для диагностики ошибок[7].
```cpp
#include <iostream>
#include <filesystem>
namespace fs = std::filesystem;
int main() {
fs::path path = "Z:\\nonexistent_folder";
std::error_code ec;
if (fs::exists(path, ec)) {
std::cout << "Папка существует.\n";
} else if (ec) {
std::cerr << "Ошибка: " << ec.message() << '\n';
} else {
std::cout << "Папка не существует.\n";
}
return 0;
}
```
Эти подходы позволяют избежать неожиданных исключений и более корректно обрабатывать ситуации, когда диск или путь недоступен.
[1] https:/github.com/microsoft/STL/issues/615
[2] https:/stackoverflow.com/questions/63486126/strange-operator-of-stdfilesystempath
[3] https://ru.stackoverflow.com/questions/1018921/Как-проверить-создана-папка-или-это-ошибка-на-самом-деле
[4] https:/stackoverflow.com/questions/72678527/version-of-stdfilesystemequivalent-for-non-existing-files
[5] https:/en.cppreference.com/w/cpp/filesystem/filesystem_error
[6] https:/developercommunity.visualstudio.com/t/std::filesystem::exists-throws-exeption/10505077?sort=active&topics=windows+10.0
[7] https://ru.stackoverflow.com/questions/1565237/в-чем-ошибка-filesystemexists
Ну, вот тебе развернутый ответ:
The current behavior appears to be the correct behavior according to the spec.exists() calls status§ or status(p, ec), as per https://eel.is/c++draft/fs.op.exists#2. status§ throws an exception if the resulting file type would be file_type::none, as per https://eel.is/c++draft/fs.op.status#1 . file_type::none is returned any time it cannot even be determined if the path exists ( https://eel.is/c++draft/fs.op.status#6.1 ), which includes any type of I/O or other hardware device failure. The hardware device is returning an I/O error (from the message it sounds like ERROR_NOT_READY). ERROR_NOT_READY is neither an indication that some element of the path does not exist (meaning not file_type::not_found), nor is it an indication that the path does exist but that there was an error determining the attributes (meaning not file_type::unknown), so the only reasonable answer is file_type::none, leading to that exception.
If you want a completely noexcept version, consider the overload accepting a std::error_code.
Billy O’Neal
Visual C++ Libraries