C++学习之路:filesystem文件系统的使用(C++17特性)
目录
- 基础介绍以及依赖
- 基础使用
- 一、创建/删除 文件/目录
- 二、检查文件类型
- 三、遍历文件夹
- 四、简单测试代码
基础介绍以及依赖
filesystem是C++17新引入的一个库,主要是用来操作文件系统,例如常用的文件夹以及文件的创建,销毁,索引等操作(内容编辑仍使用fstream库)。由于这个特性是C++17引入的,所以要检查编译器的版本是否支持C++17,VsCode中编译器版本的更改请参考这篇文章。这里提醒几点:
- 如果系统中存在多个C/C++编译器,请在系统环境的Path中将要用的编译器放在前面,使用g++/gcc --version来查询更新是否成功。
- 在VsCode中要重新配置c_cpp_properties,尤其是编译器路径以及包含路径。
在配置完成后,应该在程序开始时这样声明:
#include <filesystem>
namespace fs = std::filesystem;
其余的库,例如<sstream>\ <fstream>等就依据需要自行添加。
基础使用
首先弄明白一点:文件名(filename)和路径(path)是不同的。例如,dir1/dir2/file1.txt
是path,而对应的filename是file1.txt
;dir1/dir2
是path,对应的filename是dir2
,但不推荐用这种写法去获取dir2下内容,一般获取dir2目录下的内容我们使用dir1/dir2/
表示指向dir2内的内容;
一、创建/删除 文件/目录
创建目录使用creat_directories()
方法
创建文件使用ofstream()
方法
const fs::path sandbox{"sandbox"}; //首先定义一个路径对象(path类,sandbox是实例对象)fs::create_directories(sandbox/"dir1"/"dir2");//然后再创建一个两级的目录std::ofstream{sandbox/"file1.txt"}; //在sandbox下创建文件std::ofstream{sandbox/"file2.txt"};
删除文件/目录使用remove()
方法:
fs::remove(path);//文件和目录都可以
删除整个目录下的文件remove_all()
方法:
fs::remove_all(sandbox);
二、检查文件类型
有时候需要检查当前path指向的对象是一个目录还是一个文件,这时候就需要进行文件类型检查了。fs库给我们提供了is_regular_file(path)
方法来确定path指向的是不是一个普通文件:
if (fs::is_regular_file(path)) { // 检查是否为普通文件
xxxx;//对文件的操作
}
三、遍历文件夹
在filesystem中有一个directory_iterator类,能够获取文件系统目录中文件的迭代器容器。
使用fs::directory_iterator(dir_path)
来创建一个迭代器,用于遍历某个目录下的文件:
for (auto const& dir_entry : fs::directory_iterator(dirpath)) {std::cout << dir_entry.path() << '\n';}
这是一个基于范围的for循环,dir_entry被定义为directory_iterator迭代器内的元素,for循环对其进行遍历。
如果目录结构是下面这样的:
dir1/
├── file1.txt
├── file2.txt
└── subdir/file3.txt
输出为:
dir1/file1.txt
dir1/file2.txt
dir1/subdir (下一级的不能迭代到)
如果涉及多层的文件结构,可以使用fs::recursive_directory_iterator(dir_path)
迭代器来遍历所有的子文件夹以及其中的文件。
for (auto const& dir_entry : fs::recursive_directory_iterator{sandbox}) {std::cout << dir_entry << '\n';}
如果目录结构是下面这样的:
dir1/
├── file1.txt
├── file2.txt
└── subdir/file3.txt
输出为:
dir1/file1.txt
dir1/file2.txt
dir1/subdir/file3.txt (可以直接迭代到最后一级)
四、简单测试代码
#include <fstream>
#include <iostream>
#include <filesystem>
#include <algorithm>int main()
{const std::filesystem::path sandbox{"sandbox"};std::filesystem::create_directories(sandbox/"dir1"/"dir2");std::ofstream{sandbox/"file1.txt"};std::ofstream{sandbox/"file2.txt"};std::cout << "directory_iterator:\n";// directory_iterator can be iterated using a range-for loopfor (auto const& dir_entry : std::filesystem::directory_iterator{sandbox}) {std::cout << dir_entry.path() << '\n';}//对比filenamefor (auto const& dir_entry : std::filesystem::directory_iterator{sandbox}) {std::cout << dir_entry.path().filename() << '\n';}std::cout << "\nrecursive_directory_iterator:\n";for (auto const& dir_entry : std::filesystem::recursive_directory_iterator{sandbox}) {std::cout << dir_entry << '\n';}// delete the sandbox dir and all contents within it, including subdirsstd::filesystem::remove_all(sandbox);
}
输入结果为:
directory_iterator:
“sandbox\dir1”
“sandbox\file1.txt”
“sandbox\file2.txt”
“dir1”
“file1.txt”
“file2.txt”
recursive_directory_iterator:
“sandbox\dir1”
“sandbox\dir1\dir2”
“sandbox\file1.txt”
“sandbox\file2.txt”