[现代C++]文件系统操作

2024-07-18 13:33:40 浏览数 (2)

作为一名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 项目在文件管理方面更加高效、可靠。

0 人点赞