C++17文件系统



C++ 17 文件系统

  • file : 存放数据的文件系统对象,可读可写。拥有文件名字和属性。
    • directory : 文件目录
    • hard link : 硬链接
    • symbolic link : 符号链接
    • regular file : 常规文件
  • file name : 文件的名字,通常为一个字符串
  • path
    • absolute path : 绝对路径
    • canonical path : 规范路径(不包含符号链接,... 的路径)
    • relative path : 相对路径(一个路径相对于另一个路径的路径,字符串中可能包含 ...

path 类

文件系统中对于路径名的定义包括以下几个部分

  • ``` path name syntax

    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

    - `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 #include namespace fs = std::filesystem;

    int main() { fs::path p1 = "/a/b/c/d"; std::cout << p1.remove_filename() << ''; // /a/b/c return 0; }

    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

    - `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 #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
    1
    2
    3
    4
    5
    6
    7



    :



    perms
    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_options
    • replace
    • add
    • remove
    • nofollow

copy_options 枚举类

  • none
  • skip_existing : Keep the existing file, without reporting an error.
  • overwrite_existing : Replace the existing file
  • update_existing : Replace the existing file only if it is older than the file being copied
  • recursive : Recursively copy subdirectories and their content
  • copy_symlinks : Copy symlinks as symlinks, not as the files they point to
  • skip_symlinks : Ignore symlinks
  • directories_only : Copy the directory structure, but do not copy any non-directory files
  • create_symlinks : Instead of creating copies of files, create symlinks pointing to the originals
  • create_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

gulrak/filesystem: An implementation of C++17 std::filesystem for C++11 /C++14/C++17/C++20 on Windows, macOS, Linux and FreeBSD. (github.com)