本文将针对常用的场景,对 std::filesystem 的使用逐一进行验证:

  1. 判断文件夹是否存在
  2. 创建单层目录
  3. 逐级创建多层目录
  4. 创建多级目录
  5. 当前文件路径
  6. 创建文件"from.dat"
  7. 获取相对于base的绝对路径
  8. 文件拷贝
  9. 移动文件或重命名
  10. 创建文件 “example.dat
  11. 获取文件大小
  12. 获取文件最后修改时间
  13. 删除文件
  14. 递归删除目录下所有文件
  15. 在临时文件夹下创建文件夹并删除

一、Cpp 17 的支持

cppreference - filesystem

# Sample CMakeLists.txt
cmake_minimum_required(VERSION 3.21) # Define a CMake project project(
simple_executable_fileSystem
VERSION 1.0
DESCRIPTION "A simple C++ project to demonstrate basic CMake usage"
LANGUAGES CXX) # include_directories(include) # find_package(fmt CONFIG REQUIRED)
find_package(fmt QUIET)
if (NOT fmt_FOUND)
message(WARNING "fmt not found, skipping vcpkg example")
endif () add_executable(simple_executable_with_vcpkg) target_include_directories(simple_executable_with_vcpkg
PUBLIC include
) target_compile_features(
simple_executable_with_vcpkg
PRIVATE cxx_std_17 # 设定 CXX 17 标准
) target_sources(
simple_executable_with_vcpkg
PRIVATE src/main.cpp
) target_link_libraries(
simple_executable_with_vcpkg
PRIVATE fmt::fmt-header-only
)

二、头文件和命名空间

#include<filesystem>
using namespace std::filesystem;

三、常用类

path 类:说白了该类只是对字符串(路径)进行一些处理,这也是文件系统的基石。

directory_entry 类:功如其名,文件入口,这个类才真正接触文件。

directory_iterator 类:获取文件系统目录中文件的迭代器容器,其元素为 directory_entry对象(可用于遍历目录)

file_status 类:用于获取和修改文件(或目录)的属性(需要了解C++11的强枚举类型(即枚举类))

四、使用用法

  1. 需要有一个path对象为基础,如果需要修改路径,可以调用其成员函数进行修改(注意其实只是处理字符串)。
  2. 需要获取文件信息需要通过path构造directory_entry,但需要path一定存在才能调用构造,所以需要实现调用exists(path .)函数确保目录存在才能构造directory_entry(注意文件入口中的exists无法判断)。
  3. 若需遍历,则可以使用 directory_iterator,进行遍历

Samples

// Sample 1
#include <iostream>
#include <filesystem> using namespace std;
using namespace std::filesystem; int main() {
path str("C:\\Windows");
if (!exists(str)) //必须先检测目录是否存在才能使用文件入口.
return 1;
directory_entry entry(str); //文件入口
if (entry.status().type() == file_type::directory) //这里用了C++11的强枚举类型
cout << "该路径是一个目录" << endl;
directory_iterator list(str); //文件入口容器
for ( auto & it : list )
cout << it.path().filename() << endl; //通过文件入口(it)获取path对象,再得到path对象的文件名,将之输出
system("pause");
return 0;
}
// Sample 2
#include <fmt/core.h>
#include <filesystem>
#include <fstream>
#include <string>
#include <cassert> namespace fs = std::filesystem; int main() {
// 1> 判断文件夹是否存在
std::string dirName{ "log" };
fs::path url(dirName);
if (!fs::exists(url))
{
// fmt::print("{} is not exist\n", std::quoted(dirName)); // CXX14 引入std::quoted用于给字符串添加双引号
fmt::print("\"{}\" is not exist\n", dirName);
}
else
{
fmt::print("\"{}\" is exist\n", dirName);
} // <2> 创建单层目录 in build directories
bool okey = fs::create_directories(dirName);
fmt::print("create_directories({}), result = {}\n", dirName, okey); // <3> 逐级创建多层目录
std::error_code err;
std::string subDir = dirName + "/subdir";
okey = fs::create_directories(subDir, err);
fmt::print("create_directories({}), result = {}\n", subDir, okey);
fmt::print("err.value() = {}, err.message() = {}\n", err.value(), err.message()); // <4> 创建多级目录
dirName = "a/b//c/d/";
okey = fs::create_directories(dirName, err);
fmt::print("create_directories({}), result = {}\n", dirName, okey);
fmt::print("err.value() = {}, err.message() = {}\n", err.value(), err.message()); // <5> 当前文件路径
fs::path currentPath = fs::current_path(); // D:\Coding\CLion\Cpp17-Complete-Guide\build\simple_executable
fmt::print("currentPath = {}\n", currentPath.string());
fmt::print("root_directory = {}\n", currentPath.root_directory().string());
fmt::print("relative_path = {}\n",
currentPath.relative_path().string()); // Coding\CLion\Cpp17-Complete-Guide\build\simple_executable
fmt::print("root_name = {}\n", currentPath.root_name().string());
fmt::print("root_path = {}\n", currentPath.root_path().string()); // <6> 创建文件"from.dat"
fs::path oldPath(fs::current_path() / "from.dat");
std::fstream file(oldPath, std::ios::out | std::ios::trunc);
if (!file)
{
fmt::print("Create file ({}) failed!!!\n", oldPath.string());
}
file.close(); // <7> 获取相对于base的绝对路径
fs::path absPath = fs::absolute(oldPath/*, fs::current_path()*/);
fmt::print("absPath = {}\n", absPath.string()); // <8> 文件拷贝
fs::create_directories(fs::current_path() / "to");
fs::path toPath(fs::current_path() / "to/from0.dat");
fs::copy(oldPath, toPath); // <9> 移动文件或重命名
fs::path newPath(fs::current_path() / "to/to.dat");
fs::rename(oldPath, newPath); // <10> 创建文件 "example.dat"
fs::path _path = fs::current_path() / "example.dat";
fmt::print("example.data path: {}\n", _path.string());
std::ofstream(_path).put('a'); // create file of size 1
std::ofstream(_path).close(); // 文件类型判定
assert(fs::file_type::regular == fs::status(_path).type()); // <11> 获取文件大小
auto size = fs::file_size(_path);
fmt::print("file_size = {}\n", size); // <12> 获取文件最后修改时间
auto time = fs::last_write_time(_path);
fmt::print("last_write_time = {}\n", time.time_since_epoch().count()); // <13> 删除文件
okey = fs::remove(_path);
fmt::print("remove ({})\n", _path.string()); // <14> 递归删除目录下所有文件,返回被成功删除的文件个数
uintmax_t count = fs::remove_all(dirName);//dirName="a/b//c/d/",会把d目录也删掉
fmt::print("remove_all ({}), {}\n", dirName, count); // <15> 在临时文件夹下创建文件夹并删除
fs::path tmp = fs::temp_directory_path();//"C:\Users\Kandy\AppData\Local\Temp\"
fmt::print("temp_directory_path = {}\n", tmp.string());
fs::create_directories(tmp / "_abcdef/example");
std::uintmax_t n = fs::remove_all(tmp / "_abcdef");
fmt::print("Deleted {} files or directories\n", n); return 0;
}

五、常用库函数

void copy(const path& from, const path& to) :目录复制

path absolute(const path& pval, const path& base = current_path()) :获取相对于base的绝对路径

bool create_directory(const path& pval) :当目录不存在时创建目录

bool create_directories(const path& pval) :形如/a/b/c这样的,如果都不存在,创建目录结构

bool exists(const path& pval) :用于判断path是否存在

uintmax_t file_size(const path& pval) :返回目录的大小

file_time_type last_write_time(const path& pval) :返回目录最后修改日期的file_time_type对象

bool remove(const path& pval) :删除目录

uintmax_t remove_all(const path& pval) :递归删除目录下所有文件,返回被成功删除的文件个数

void rename(const path& from, const path& to) :移动文件或者重命名

库函数 | C++17 std::filesystem文件系统 用法指北的更多相关文章

  1. C++17 std::shared_mutex的替代方案boost::shared_mutex

    C++17 std::shared_mutex的替代方案boost::shared_mutex C++17boost  std::shared_mutex http://en.cppreference ...

  2. Python 简单入门指北(二)

    Python 简单入门指北(二) 2 函数 2.1 函数是一等公民 一等公民指的是 Python 的函数能够动态创建,能赋值给别的变量,能作为参传给函数,也能作为函数的返回值.总而言之,函数和普通变量 ...

  3. Python 简单入门指北(一)

    Python 简单入门指北(一) Python 是一门非常容易上手的语言,通过查阅资料和教程,也许一晚上就能写出一个简单的爬虫.但 Python 也是一门很难精通的语言,因为简洁的语法背后隐藏了许多黑 ...

  4. 可能比文档还详细--VueRouter完全指北

    可能比文档还详细--VueRouter完全指北 前言 关于标题,应该算不上是标题党,因为内容真的很多很长很全面.主要是在官网的基础上又详细总结,举例了很多东西.确保所有新人都能理解!所以实际上很多东西 ...

  5. 颓废选手在 Ubuntu/Noilinux 下的生存指北

    颓废选手在 Ubuntu/Noilinux 下的生存指北 Hint: 这里的 "#" 都是假注释,复制的时候记得删除 一些基本的生存命令 ctrl + alt + t #调出终端 ...

  6. Markdown 标记语言指北 - 源码

    这是上一篇博客的源代码. 这是班刊约稿的一篇文章. 全文约6000字, 预计需要 60 分钟读完. # Markdown 标记语言指北 #### TOC 1. [什么是 Markdown?](#%E4 ...

  7. ansible使用指北(二)

    前言在上一篇文章里我们了解了ansible的常用模块,今天我们来了解下ansible-playbook,ansbile-playbook是一系统ansible命令的集合,其利用yaml 语言编写,an ...

  8. WEB安全漏洞挖掘向入坑指北

    这个指北不会给出太多的网站和方向建议,因为博主相信读者能够从一个点从而了解全局,初期的时候就丢一大堆安全网址导航只会浇灭人的热情,而且我也不适合传道授业解惑hhh 安全论坛: 先知社区 freebuf ...

  9. git宝典—应付日常工作使用足够的指北手册

    最近公司gitlab又迁移,一堆git的命令骚操作,然鹅git命令,感觉还是得复习下——其实,git现在界面操作工具蛮多,比如intellij 自带的git操作插件就不错,gitlab github ...

  10. 关于supervisor的入门指北

    关于supervisor的入门指北 在目前这个时间点(2017/07/25),supervisor还是仅支持python2,所以我们要用版本管理pyenv来隔离环境. pyenv 根据官方文档的讲解, ...

随机推荐

  1. 安全测试工具Burpsuit和OWASP ZAP使用入门指南

    Burpsuit使用入门指南 安装: 网上有很多相关相关保姆级别教程,所以这里不加赘述了 尽量使用java8版本,破解版兼容8做的比较好 如果发现注册机无法打开或者能打开注册机[run]无法点击唤起软 ...

  2. 向“创新者”升阶,程序员当下如何应对 AI 的挑战

    随着 AI 技术的飞速发展,特别是大模型的出现,传统的程序员角色正在经历深刻的变革,我们不得不重新对自己进行审视和思考. 通用领域大模型的"泛化能力" 在过去的二十年内,AI 领域 ...

  3. nordic的nrf52系列32M速率的SPI-SPIM3

    简介:在nordic的nrf52系列中的nrf52833和nrf52840的SPIM3都是支持最大32M的spi速率,其余的只有8M,当在需要刷屏,或者一些需要高速32M-SPI时,这是一个很好的使用 ...

  4. 构建一个语音转文字的WebApi服务

    构建一个语音转文字的WebApi服务 简介 由于业务需要,我们需要提供一个语音输入功能,以便更方便用户的使用,所以我们需要提供语音转文本的功能,下面我们将讲解使用Whisper将语音转换文本,并且封装 ...

  5. 【UniApp】-uni-app-扩展组件

    前言 好,经过上个章节的介绍完毕之后,了解了一下 uni-app-内置组件 那么了解完了uni-app-内置组件之后,这篇文章来给大家介绍一下 UniApp 中的扩展组件 首先不管三七二十一,先来新建 ...

  6. .Net 8与硬件设备能碰撞出怎么样的火花(使用ImageSharp和Protobuf协议通过HidApi与设备通讯)

    前言 本人最近在社区里说想做稚晖君的那个瀚文键盘来着,结果遇到两个老哥一个老哥送了我电路板,一个送了我焊接好元件的电路板,既然大家这么舍得,那我也就真的投入制作了这把客制化键盘,当然我为了省钱也是特意 ...

  7. 数字孪生技术与VR技术的结合会为我们带来什么?

    数字孪生技术与虚拟现实(VR)技术的结合为我们打开了全新的可能性和机遇.这个强大的联合为各个领域带来了巨大的影响和创新. 首先,数字孪生技术与VR技术的结合可以为设计和规划过程提供更直观.身临其境的体 ...

  8. 去年最火的 JS 开源项目「GitHub 热点速览」

    近日,「Best of JS」发布了过去一年在 GitHub 上 Star 数增速最快的 JavaScript 开源项目(2023 JavaScript Rising Stars),前 10 的开源项 ...

  9. .NET Web应用配置本地IIS(实现Visual Studio离线运行与调试)

    前言: 因为项目程序需要频繁的修改,然后每次修改以后都要重新编译才能查看到修改的效果.而且有时候前端也需要及时的对接我们的接口,导致每次修改一点东西都要发布一次,这样子对于开发者而言是十分的浪费时间, ...

  10. 率先支持Kuasar!iSulad Sandbox API 简化调用链,沙箱管理能力增强

    本文分享自华为云社区<率先支持Kuasar!iSulad Sandbox API 简化调用链,可靠性倍增>,作者:云容器大未来 . 沙箱隔离技术是一种将进程有效隔离到独立环境中运行的技术. ...