C++ 17 文件系统
file
: 存放数据的文件系统对象,可读可写。拥有文件名字和属性。directory
: 文件目录hard link
: 硬链接symbolic link
: 符号链接regular file
: 常规文件
file name
: 文件的名字,通常为一个字符串path
absolute path
: 绝对路径canonical path
: 规范路径(不包含符号链接,.
和..
的路径)relative path
: 相对路径(一个路径相对于另一个路径的路径,字符串中可能包含.
和..
)
path 类
文件系统中对于路径名的定义包括以下几个部分
``` path name syntax
#include1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
- `root-name` : 根的名字,例如 `C:` 或 `//myserver`
- `root-directory` : 根目录,将该路径标记为绝对路径的目录分隔符。
- `file-name` : 文件名
- `directory-separator` : 目录分隔符
path 类有一个常成员变量 `constexpr value_type preferred_separator`。在 windows 系统中为 `\`,在 POSIX 中为 `/`。
### 路径规范化算法
path 可以通过以下算法进行规范化:
1. 如果路径为空,则停止;
2. 替换连续的多个目录分隔符为单独的一个 `preferred_separator`,eg: `/usr///////lib` -> `/usr/lib`
3. 替换 `root-name` 中的每个斜杠字符为 `prefered_separator`
4. 移除紧跟斜杠字符后的 `.` 符号
5. 移除紧跟斜杠字符后的 `..` 符号,并将 `..` 前的非 `..` 文件名去掉,eg: `/usr/local/include/../opencv2` -> `/usr/local/include/opencv2`
6. 如果存在根目录,删除所有 `..` 和紧随其后的所有目录分隔符
7. 如果最后一个文件名是 `..`,删除所有结尾的目录分隔符
8. 如果路径为空,则添加 `.`
### 路径的格式
路径有两种格式,`native_format` 和 `generate_format`。对于 POSIX-like 的文件系统,这两种格式是相同的。对于 Windows 文件系统,则是不同的。
- generic format 路径格式:`/home/mypc/myfile.txt`
- native format 路径格式(windows):`F:\\MyDirectory\\myFile.txt` 或 `F:\MyDirectory\myFile.txt`
### 路径的操作
- `(constructor)` & `(destructor)` & `operator=` & `assign`
- 路径有构造函数和析构函数,可以通过 `operator=` 进行赋值,也可以使用 `assign` 进行赋值。
- `append` & `operator/=` & `concat` & `operator+=`
- 路径有两个连接操作,`operator/=` 和 `append` 可以将两个路径进行连接,同时会添加一个分隔符。`operator+=` 和 `concat` 也可以将两个路径进行连接,但是不会添加分隔符。
- `clear` : 清除路径中的内容
- `swap` : 交换两个路径中的内容
- `make_preferred` : 将路径中的分隔符替换为 `preferred_separator`
- `remove_filename` : 将路径中的文件名去掉,具体是指删除最后一个文件分隔符之后的内容
Cpp
#include namespace fs = std::filesystem; int main() { fs::path p1 = "/a/b/c/d"; std::cout << p1.remove_filename() << ''; // /a/b/c return 0; }
#include1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
- `replace_filename` : 替换路径中的最后一部分为其他路径
- `replace_extension` : 替换文件后缀
- `c_str` & `native` & `operator string_type`
- 将路径转换为字符串
- `string` & `wstring` & `u8string` & `u16string` & `u32string`
- 根据具体的编码将路径转换为具体的 native 字符串格式
- `generic_string` & `generic_wstring` & `generic_u8string` & `generic_u16string` & `generic_u32string`
- 根据具体的编码将路径转换为具体的 generic 字符串格式
- `compare` : 比较两个路径
- `lexically_normal` : 转换路径为 normal 格式(不包含 `.` 和 `..`)
- `lexically_relative` : 转换路径为 relative 格式
- `lexically_proximate` : 转换路径为 proximate 格式
- `empty` : 检测路径是否为空
- `is_absolute` : 检查路径是否为绝对路径
- `is_relative` : 检查路径是否为相对路径
- `begin` : begin 迭代器
- `end` : end 迭代器
- 迭代器所指向的序列包括:
- `root-name`
- `root-directory`
- sequence of `file-name`(不包括分隔符)
- 如果路径最后是分隔符,则序列的最后一个为空字符串
Cpp
#include namespace fs = std::filesystem;
int main() { fs::path p = R"(C:)"; for (auto it = p.begin(); it != p.end(); it++) { std::cout << *it << ''; } for (auto & e : p) { std::cout << e << ''; } return 0; } // Output: // "C:" // "\" // "Users" // "yangshun" // "AppData" // "Local" // "Temp" // ""
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
获取以及检查路径的几个部分
| 获取函数 | 检查函数 | 描述 |
| :--------------- | :------------------- | :---------------------------------------------------- |
| `root_name` | `has_root_name` | 获取(检查)路径根的名字 |
| `root_directory` | `has_root_directory` | 获取(检查)路径根目录(绝对路径的目录分隔符) |
| `root_path` | `has_rootpath` | 获取(检查)根路径,`root_name` + `root_directory` |
| `relative_path` | `has_relative_path` | 获取(检查)相对路径,除去 `root_path` 之后剩余的部分 |
| `parent_path` | `has_parent_path` | 获取(检查)除去文件名外的路径部分 |
| `filename` | `has_filename` | 获取(检查)文件名 |
| `stem` | `has_stem` | 获取(检查)文件名称 |
| `extension` | `has_extension` | 获取(检查)文件扩展 |
##
## filesystem_error 类
`filesystem_error` 类是在对文件系统进行操作出现异常是抛出的错误,其成员变量包括 `(constructor)`, `operator=`, `path1`, `path2` 和 `what`。`path1` 和 `path2` 是造成异常的路径。
## directory_entry 类
`directory_entry` 代表目录条目。其对象会存储一个路径以及额外的一些文件属性(hard link count, status, symlink status file size, and last write time)
- `(constructor)` & `(destructor)` & `operator=` & `assign`
- `replace_filename` : 更改目录条目的文件名
- `refresh` : 刷新文件系统对象的属性状态
- `path` : 返回目录条目引用的完整路径
- `exists` : 检查目录条目是否存在
- `is_block_file` : 检查目录条目是否为块设备
- `is_character_file` : 检查目录条目是否为字符设备
- `is_directory` : 检查目录条目是否为目录
- `is_fifo` : 检查目录条目是否为命名管道
- `is_other` : 检查目录条目是否为其他文件
- `is_regular_file` : 检查目录条目是否引用常规文件
- `is_socket` : 检查目录条目是否引用常规文件
- `is_symlink` : 检查目录条目是否引用符号链接
- `file_size` : 返回目录条目引用的文件的大小
- `hard_link_count` : 返回引用目录条目所引用文件的硬链接数
- `last_write_time` : 获取或设置目录条目所引用文件的最后一次数据修改的时间
- `status` & `symlink_status` : 目录条目指定的文件的状态
## directory_iterator 类
- 指向 directory_entry 中元素的迭代器,类型为输入迭代器。该迭代器不会遍历子文件夹。
## recursive_directory_iterator 类
- 指向 directory_entry 中元素的迭代器,类型为输入迭代器。该迭代器会遍历所有子文件夹。除了迭代器通有的操作外,该迭代器还包括以下函数
- `depth` : 返回当前递归的深度
- `recursion_pending` : 检查是否对当前目录禁用了递归
- `pop` : 在目录层次结构中将迭代器上移一级
- `disable_recuresion_pending` : 禁用递归,直到下一个增量
## file_status 类
`file_status` 类存储了文件的类型和权限信息,`type` 函数可以获取或设置文件类型(返回 `file_type` 枚举类),`permissions` 函数可以获取或设置文件的权限(返回 `perms` 类)
## space_info 结构体
表示由空间确定的文件系统信息。包括 `capcity`, `free` 和 `available`.
## file_type 枚举类
- ```
type:
1
file_type
none
not_found
regular
directory
symlink
block
character
fifo
socket
perms 枚举类
- ``` permissions perms
1
2
3
4
5
6
7
:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
- `none`
- `owner_read`
- `owner_write`
- `owner_exec`
- `owner_all`
- `group_read`
- `group_write`
- `group_exec`
- `group_all`
- `others_read`
- `others_write`
- `others_exec`
- `others_all`
- `all`
- `set_uid`
- `set_gid`
- `sticky_bit`
- `mask`
## perm_options 枚举类
- ```
perm_optionsreplace
add
remove
nofollow
copy_options 枚举类
none
skip_existing
: Keep the existing file, without reporting an error.overwrite_existing
: Replace the existing fileupdate_existing
: Replace the existing file only if it is older than the file being copiedrecursive
: Recursively copy subdirectories and their contentcopy_symlinks
: Copy symlinks as symlinks, not as the files they point toskip_symlinks
: Ignore symlinksdirectories_only
: Copy the directory structure, but do not copy any non-directory filescreate_symlinks
: Instead of creating copies of files, create symlinks pointing to the originalscreate_hard_links
: Instead of creating copies of files, create hardlinks that resolve to the same files as the originals
函数
absolute
: 获取绝对路径canonical
: 获取典型路径格式,会去掉.
和..
relative
: 获取相对路径,默认为相对于当前路径的路径copy
: 拷贝文件或者目录copy_file
: 拷贝文件内容copy_symlinks
: 拷贝符号链接create_directory
: 创建目录create_hard_link
: 创建硬链接create_symlink
&create_directory_symlink
: 创建符号链接current_path
: 当前目录exists
: 检查路径是否存在equivalent
: 检查两个路径是否相等file_size
: 获取文件的大小hard_link_count
: 获取硬链接的数量last_write_time
: 获取或者设置数据修改的最后时间permissions
: 修改文件权限read_symlink
: 获取符号链接的目标remove
: 删除一个文件或者空目录remove_all
: 删除一个文件或者递归删除一个文件目录rename
: 移动或者重命名文件或者目录resize_file
: 通过截断或者补零的方式改变常规文件的大小space
: 确定文件系统上的可用空间status
: 获取文件属性symlink_status
: 获取文件属性,检查符号链接目标temp_directory_path
: 获取临时目录路径
相关
文档
directory_entry 类 | Microsoft Docs
文章
C++ 17 filesystem | Busyboxs (yangshun.win)
基于c++11 的filesystem库_v6543210的专栏-CSDN博客
vs2019 问题:
Visual Studio 2019 C++ and std::filesystem - Stack Overflow
Bartek's coding blog: C++17 in details: Filesystem (bfilipek.com)
'filesystem': is not a member of std - Visual Studio Feedback
Bartek's coding blog: C++17 in details: Filesystem (bfilipek.com)
GitHub