作为一名QT开发工程师,对于QT的文件系统操作的便利性推崇备至,但在非QT程序中仅仅因为操作文件系统而集成QT库显得过于繁重。
C 17引入了std::filesystem,使得文件系统操作变得前所未有的便捷和高效。std::filesystem为我们提供了一套类型安全、异常友好的接口,让跨平台的文件和目录管理变得轻而易举。
前置条件
std::filesystem是C 17引入的新特性,所以编译器需支持C 17及以后版本。同时,文件系统操作的相应功能是在std中的filesystem命名空间内,所以在包含头文件<filesystem>的基础上,还要注意使用命名空间。
文件路径与路径操作
std::filesystem::path是std::filesystem中最核心的类,它代表文件或目录的路径。通过定义path类型的对象即可。该类型支持对于路径的检查,包括路径性质和路径存在性检查。见如下示例代码:
代码语言:javascript复制#include<filesystem>
namespacefs = std::filesystem;
fs::path filePath = "d://example.txt";
fs::path relativePath = "example.txt";
fs::path combinedPath = "../subfolder";
//后缀名
if (filePath.has_extension())
{
std::cout << "extension " << filePath.extension() << "n";
}
//文件名
if (filePath.has_filename())
{
std::cout << "filename " << filePath.filename() << "n";
}
//绝对路径检查
if (filePath.is_absolute())
{
std::cout << "Absolute pathn";
}
//相对路径检查
if (relativePath.is_relative())
{
std::cout << "Relative pathn";
}
//存在性检查
if (fs::exists(filePath)) {
std::cout << "Path exists.n";
}
文件目录
std::filesystem支持文件夹的创建、移除,并支持文件夹存在性、文件夹的子文件夹检查,同时可以支持磁盘剩余空间、文件夹属性的检查。
代码语言:javascript复制std::cout<<"current path "<< fs::current_path().string()<<"n";
//检查文件夹是否存在
//不存在则创建
if (!fs::exists("d://programer"))
{
//父目录必须存在,否则会抛出异常
//文件存在时,创建失败
bool create_ret = fs::create_directory("d://programer");
std::cout << "create create_directory of 'd://programer' result " << create_ret << "n";
}
else
{
std::cout << "directory of 'd://programer' has existed do not need create"<< "n";
}
//检查当前文件夹是否存在子文件夹
if (!fs::path("d://programer").has_stem())
{
//有子文件夹时使用remove方法会报错
bool create_ret = fs::remove("d://programer");
std::cout << "remove of 'd://programer' result " << create_ret << "n";
}
else
{
std::cout << "directory of 'd://programer' has stem, cannot use remove, so use remove_all " << "n";
//递归删除
bool create_ret = fs::remove_all("d://programer");
std::cout << "remove_all of 'd://programer' result " << create_ret << "n";
}
//递归创建目录,父目录不存在也可以正确创建
bool create_ret = fs::create_directories("d://programer/pro/pro/hello");
std::cout<<"create create_directories of 'd://programer/pro/pro/hello' result "<<create_ret << "n";
create_ret = fs::remove_all("d://programer");
std::cout << "remove_all directories of 'd://programer/pro/pro/hello' result " << create_ret << "n";
auto spaceinfo = fs::space("D://");
std::cout<<" available="<<spaceinfo.available / (1024 * 1024 * 1024) << //剩余空间
" capacity=" << spaceinfo.capacity/(1024*1024*1024) << //总空间
" free=" << spaceinfo.free / (1024 * 1024 * 1024) << "n";//剩余空间
auto status = fs::status("D://");
std::cout << " type=" << (int)status.type() //类型,表征目录、socket等
<< " permissions=" << (int)status.permissions() << "n";//权限,如读写等
同时支持文件夹的遍历,如下方法将遍历文件夹下的所有文件和文件夹。
代码语言:javascript复制for (constauto & entry : fs::directory_iterator("documents")) {
std::cout << entry.path() << std::endl;
}
也支持文件/文件夹的复制和重命名,方法如下:
代码语言:javascript复制 fs::copy("d://111", "d://2221", fs::copy_options::overwrite_existing);
fs::rename("d://111", "d://22222");
异常处理
std::filesystem操作会因为文件/文件夹不存在、已存在、权限不够等而出现异常,因此需要注意调用函数的标志位,如copy方法中的copy_options标志位;也需要注意处理异常,如下
代码语言:javascript复制try {
fs::copy("source.txt", "destination.txt");
} catch (constfs::filesystem_error& ex) {
std::cerr << "Exception caught (" << ex.what() << ")n";
}
结语
std::filesystem不仅极大地简化了文件系统的操作,还通过类型安全和异常处理机制提升了代码的健壮性。它跨越了Windows、Linux、macOS等多个平台,使得跨平台开发更加便捷。掌握这一库,无疑会使你的C 项目在文件管理方面更加高效、可靠。