当前位置: 首页 > news >正文

C++ Filesystem Library 全解

C++ Filesystem Library 全解

参考:https://en.cppreference.com/w/cpp/filesystem.html

1. path 类(路径表示)

class path {
public:// 构造函数path() noexcept;  // 创建空路径path(const path& p);  // 拷贝构造path(path&& p) noexcept;  // 移动构造path(string_type&& source);  // 从字符串构造路径template <class Source> path(const Source& source);  // 从各种字符串类型构造// 路径操作path operator/(const path& p) const;  // 路径拼接,返回新路径path& operator/=(const path& p);  // 路径拼接,修改当前路径path& replace_extension(const path& replacement = path());  // 替换扩展名// 路径分解path root_name() const;  // 返回根名称(如"C:")path root_directory() const;  // 返回根目录(如"/")path root_path() const;  // 返回根路径(如"C:/")path relative_path() const;  // 返回相对路径部分path parent_path() const;  // 返回父路径path filename() const;  // 返回文件名部分path stem() const;  // 返回主文件名(不含扩展名)path extension() const;  // 返回扩展名(包含.)// 路径转换const string_type& native() const noexcept;  // 返回原生格式路径operator string_type() const;  // 转换为原生字符串类型std::string string() const;  // 转换为UTF-8字符串std::wstring wstring() const;  // 转换为宽字符串std::u8string u8string() const;  // 转换为UTF-8字符串(C++20)std::u16string u16string() const;  // 转换为UTF-16字符串std::u32string u32string() const;  // 转换为UTF-32字符串
};

2. filesystem_error 类(文件系统异常)

class filesystem_error : public std::system_error {
public:const path& path1() const noexcept;  // 返回第一个相关路径const path& path2() const noexcept;  // 返回第二个相关路径(如果有)const char* what() const noexcept override;  // 返回错误描述
};

3. directory_entry 类(目录条目)

class directory_entry {
public:// 构造函数directory_entry() noexcept = default;  // 默认构造空条目explicit directory_entry(const filesystem::path& p);  // 从路径构造// 修改器void assign(const filesystem::path& p);  // 分配新路径void replace_filename(const filesystem::path& p);  // 替换文件名部分// 状态查询bool exists() const;  // 检查条目是否存在bool is_block_file() const;  // 是否是块设备文件bool is_character_file() const;  // 是否是字符设备文件bool is_directory() const;  // 是否是目录bool is_fifo() const;  // 是否是命名管道(FIFO)bool is_other() const;  // 是否是其他类型文件bool is_regular_file() const;  // 是否是普通文件bool is_socket() const;  // 是否是套接字文件bool is_symlink() const;  // 是否是符号链接uintmax_t file_size() const;  // 返回文件大小(字节)file_time_type last_write_time() const;  // 返回最后修改时间file_status status() const;  // 获取文件状态(可能跟随符号链接)file_status symlink_status() const;  // 获取符号链接本身状态
};

4. directory_iterator 类(目录迭代器)

class directory_iterator {
public:// 构造函数directory_iterator() noexcept;  // 创建结束迭代器explicit directory_iterator(const path& p);  // 从目录路径构造directory_iterator(const path& p, directory_options options);  // 带选项构造// 迭代器操作const directory_entry& operator*() const;  // 解引用获取当前条目const directory_entry* operator->() const;  // 成员访问directory_iterator& operator++();  // 前移迭代器directory_iterator& increment(std::error_code& ec);  // 前移迭代器(错误码版本)
};

5. recursive_directory_iterator 类(递归目录迭代器)

class recursive_directory_iterator {
public:// 构造函数recursive_directory_iterator() noexcept;  // 创建结束迭代器explicit recursive_directory_iterator(const path& p);  // 从目录路径构造recursive_directory_iterator(const path& p, directory_options options);  // 带选项构造// 迭代器操作const directory_entry& operator*() const;  // 解引用获取当前条目const directory_entry* operator->() const;  // 成员访问recursive_directory_iterator& operator++();  // 前移迭代器recursive_directory_iterator& increment(std::error_code& ec);  // 前移迭代器(错误码版本)// 递归控制void pop();  // 跳出当前目录,不再遍历其子目录int depth() const;  // 返回当前递归深度(0表示顶层目录)bool recursion_pending() const;  // 检查是否允许递归进入子目录void disable_recursion_pending();  // 禁止递归进入下一个遇到的目录
};

6. file_status 类(文件状态)

class file_status {
public:// 构造函数explicit file_status(file_type ft = file_type::none, perms prms = perms::unknown) noexcept;// 修改器void type(file_type ft) noexcept;  // 设置文件类型void permissions(perms prms) noexcept;  // 设置权限// 观察器file_type type() const noexcept;  // 获取文件类型perms permissions() const noexcept;  // 获取权限
};

7. space_info 结构(磁盘空间)

struct space_info {uintmax_t capacity;  // 总空间(字节)uintmax_t free;  // 剩余空间(字节)uintmax_t available;  // 可用空间(可能小于free)
};

8. file_type 枚举(文件类型)

enum class file_type {none = /* unspecified */,not_found = /* unspecified */,regular = /* unspecified */,directory = /* unspecified */,symlink = /* unspecified */,block = /* unspecified */,character = /* unspecified */,fifo = /* unspecified */,socket = /* unspecified */,unknown = /* unspecified */,/* implementation-defined */
};

9. perms 枚举(文件权限)

enum class perms : unsigned {// 未完全列出,完整见:https://en.cppreference.com/w/cpp/filesystem/perms.html// 所有者权限owner_read = 0400,owner_write = 0200,owner_exec = 0100,owner_all = 0700,// 组权限group_read = 040,group_write = 020,group_exec = 010,group_all = 070,// 其他用户权限others_read = 04,others_write = 02,others_exec = 01,all = 0777,// 特殊标志位set_uid = 04000,  // 设置用户IDsticky_bit = 01000  // 粘滞位
};

10. perm_options 枚举(权限操作选项)

enum class perm_options : unsigned {replace = 1,  // 替换现有权限add = 2,      // 添加权限位remove = 4,   // 移除权限位nofollow = 8  // 不跟随符号链接
};

11. copy_options 枚举(复制选项)

enum class copy_options {none = /* unspecified */,skip_existing = /* unspecified */,		// 跳过已存在文件overwrite_existing = /* unspecified */,		// 覆盖已存在文件update_existing = /* unspecified */,		// 仅更新更旧的文件recursive = /* unspecified */,				// 递归复制目录copy_symlinks = /* unspecified */,			// 复制符号链接本身skip_symlinks = /* unspecified */,directories_only = /* unspecified */,create_symlinks = /* unspecified */,		// 创建符号链接而非复制内容create_hard_links = /* unspecified */
};

12. directory_options 枚举(目录迭代选项)

enum class directory_options {none = /* unspecified */,follow_directory_symlink = /* unspecified */,	// 跟随目录符号链接skip_permission_denied = /* unspecified */		// 跳过无权限目录
};

13. file_time_type(文件时间类型)

using file_time_type = std::chrono::time_point</*trivial-clock*/>;
// /*trivial-clock*/ 是一个满足 TrivialClock 的实现定义类型,足以表示文件系统提供的文件时间值的分辨率和范围。
using file_time_type = std::chrono::time_point<std::chrono::file_clock>;

典型使用示例

// 递归计算目录大小
uintmax_t calculate_directory_size(const fs::path& dir) {uintmax_t total = 0;for (const auto& entry : fs::recursive_directory_iterator(dir)) {if (entry.is_regular_file()) {total += entry.file_size();}}return total;
}// 设置文件权限
void make_executable(const fs::path& file) {fs::permissions(file, fs::perms::owner_exec | fs::perms::group_exec | fs::perms::others_exec,fs::perm_options::add);
}

这个库提供了跨平台的文件系统操作能力,所有路径分隔符会自动适应目标操作系统,极大简化了跨平台文件操作的开发工作。


非成员函数详解

以下是 <filesystem> 中所有非成员函数的详细讲解,按照您提供的顺序组织:

1. 路径组合函数

absolute - 获取绝对路径

path absolute(const path& p);  // 相对于当前目录的绝对路径
path absolute(const path& p, std::error_code& ec);  // 错误码版本
  • 功能:将相对路径转换为绝对路径
  • 注意:不检查路径是否存在,仅做路径组合
  • 示例
    auto abs_path = fs::absolute("dir/file.txt");  // 如 "/home/user/dir/file.txt"
    

canonicalweakly_canonical - 获取规范路径

path canonical(const path& p);  // 完全规范化路径(必须存在)
path weakly_canonical(const path& p);  // 尽可能规范化(不要求存在)
  • 区别
    • canonical:要求路径必须存在,解析所有符号链接和./..
    • weakly_canonical:不要求路径存在,对存在部分进行规范化
  • 示例
    fs::create_symlink("target", "link");
    auto c = fs::canonical("link");  // 返回"target"的绝对路径
    

relativeproximate - 获取相对路径

path relative(const path& p);  // 相对于当前目录
path relative(const path& p, const path& base);  // 相对于指定目录
path proximate(const path& p);  // 类似relative,但可能返回绝对路径
  • 区别
    • relative:当无法构成相对路径时抛出异常
    • proximate:无法构成时返回绝对路径
  • 示例
    fs::path p = "/a/b/c";
    fs::path base = "/a/d";
    auto rel = fs::relative(p, base);  // "../b/c"
    

2. 文件操作函数

复制操作组

void copy(const path& from, const path& to);  // 基本复制
void copy(const path& from, const path& to, copy_options options);  // 带选项
bool copy_file(const path& from, const path& to);  // 仅复制文件内容
void copy_symlink(const path& existing, const path& newlink);  // 复制符号链接
  • 选项示例
    fs::copy("src", "dst", fs::copy_options::recursive);  // 递归复制目录
    

创建操作组

bool create_directory(const path& p);  // 创建单个目录
bool create_directories(const path& p);  // 递归创建目录
void create_hard_link(const path& target, const path& link);  // 创建硬链接
void create_symlink(const path& target, const path& link);  // 创建符号链接
void create_directory_symlink(const path& target, const path& link);  // 目录符号链接
  • 区别
    • create_directory:仅创建最后一级目录
    • create_directories:创建路径中所有不存在的目录
    • 硬链接 vs 符号链接:
      • 硬链接:直接指向文件数据
      • 符号链接:类似快捷方式

3. 路径查询函数

current_path - 工作目录操作

path current_path();  // 获取当前工作目录
void current_path(const path& p);  // 设置当前工作目录
  • 注意:设置工作目录影响整个进程

existsequivalent - 存在性检查

bool exists(const path& p);  // 路径是否存在
bool equivalent(const path& p1, const path& p2);  // 是否指向同一文件
  • 示例
    fs::create_hard_link("file.txt", "link");
    bool same = fs::equivalent("file.txt", "link");  // true
    

4. 文件属性函数

file_size - 文件大小

uintmax_t file_size(const path& p);  // 返回字节数
  • 注意:对目录调用会抛出异常

hard_link_count - 硬链接计数

uintmax_t hard_link_count(const path& p);  // 返回硬链接数量
  • 常规文件:通常为1
  • 目录:至少2(自身和父目录的.条目)

last_write_time - 修改时间

file_time_type last_write_time(const path& p);  // 获取时间
void last_write_time(const path& p, file_time_type new_time);  // 设置时间
  • 时间类型std::chrono::time_point

5. 权限管理

permissions - 修改权限

void permissions(const path& p, perms prms);  // 替换权限
void permissions(const path& p, perms prms, perm_options opts);  // 精细控制
  • 选项示例
    // 添加执行权限
    fs::permissions("script.sh", fs::perms::owner_exec | fs::perms::group_exec,fs::perm_options::add);
    

6. 符号链接操作

read_symlink - 读取链接目标

path read_symlink(const path& p);  // 返回符号链接指向的路径
  • 注意:对非符号链接调用会抛出异常

7. 删除和重命名

removeremove_all - 删除文件

bool remove(const path& p);  // 删除单个文件/空目录
uintmax_t remove_all(const path& p);  // 递归删除(返回删除条目数)

rename - 重命名/移动

void rename(const path& old_p, const path& new_p);  // 移动/重命名文件
  • 跨设备移动:可能需要先复制再删除

8. 特殊操作

resize_file - 调整文件大小

void resize_file(const path& p, uintmax_t new_size);  // 截断或填充0

space - 磁盘空间

space_info space(const path& p);  // 返回容量、空闲和可用空间
  • 结构体成员
    struct space_info {uintmax_t capacity;  // 总空间uintmax_t free;      // 未使用空间uintmax_t available; // 可用空间(可能小于free)
    };
    

statussymlink_status - 文件状态

file_status status(const path& p);  // 获取状态(跟随符号链接)
file_status symlink_status(const path& p);  // 获取链接本身状态

temp_directory_path - 临时目录

path temp_directory_path();  // 返回系统临时目录
  • 典型路径
    • Windows: C:\Users\Username\AppData\Local\Temp
    • Linux: /tmp

使用建议

  1. 错误处理:生产代码应使用error_code版本

    std::error_code ec;
    auto size = fs::file_size("file.txt", ec);
    if (ec) { /* 处理错误 */ }
    
  2. 跨平台注意

    • Windows路径大小写不敏感
    • 符号链接行为可能不同
  3. 性能敏感场景

    // 避免重复状态检查
    auto stat = fs::status(p);
    if (fs::is_regular_file(stat)) { /*...*/ }
    

这些函数共同构成了C++标准库完整的文件系统操作接口,覆盖了绝大多数文件操作需求。

文件类型检查函数详解

Filesystem 库提供了一系列函数用于检查路径指向的文件类型,这些函数通常有两种形式:直接接受路径和接受 file_status 对象。以下是各个类型检查函数的详细说明:

1. 基础文件类型检查函数

is_block_file - 检查块设备文件

bool is_block_file(const path& p);  // 通过路径检查
bool is_block_file(const file_status& s) noexcept;  // 通过状态检查
  • 功能:检查是否为块设备文件(如 /dev/sda
  • 典型系统:Linux/Unix 系统中的设备文件
  • 示例
    if (fs::is_block_file("/dev/sda")) {std::cout << "This is a block device\n";
    }
    

is_character_file - 检查字符设备文件

bool is_character_file(const path& p);
bool is_character_file(const file_status& s) noexcept;
  • 功能:检查是否为字符设备文件(如 /dev/tty
  • 特点:逐字符访问,无缓冲
  • 示例
    if (fs::is_character_file("/dev/tty")) {std::cout << "Character device detected\n";
    }
    

is_directory - 检查目录

bool is_directory(const path& p);
bool is_directory(const file_status& s) noexcept;
  • 最常用函数之一
  • 示例
    if (fs::is_directory("/etc")) {std::cout << "This is a directory\n";
    }
    

is_empty - 检查是否为空

bool is_empty(const path& p);
  • 功能
    • 对文件:检查文件大小为0
    • 对目录:检查是否没有子项
  • 注意:对特殊文件类型(如设备文件)行为可能不同
  • 示例
    if (fs::is_empty("empty.txt")) {std::cout << "File is empty\n";
    }
    

2. 特殊文件类型检查函数

is_fifo - 检查命名管道

bool is_fifo(const path& p);
bool is_fifo(const file_status& s) noexcept;
  • 功能:检查是否为 FIFO(命名管道)文件
  • 典型创建方式mkfifo 命令
  • 示例
    if (fs::is_fifo("my_pipe")) {std::cout << "Named pipe found\n";
    }
    

is_socket - 检查 Unix 域套接字

bool is_socket(const path& p);
bool is_socket(const file_status& s) noexcept;
  • 功能:检查是否为 Unix 域套接字文件
  • 典型路径/tmp 目录下的套接字文件
  • 示例
    if (fs::is_socket("/tmp/mysql.sock")) {std::cout << "Socket file detected\n";
    }
    

is_other - 检查其他类型文件

bool is_other(const path& p);
bool is_other(const file_status& s) noexcept;
  • 功能:检查是否为非常规文件类型
  • 判断逻辑!is_regular_file() && !is_directory() && !is_symlink()
  • 典型情况:设备文件、套接字、管道等

3. 常规文件检查函数

is_regular_file - 检查普通文件

bool is_regular_file(const path& p);
bool is_regular_file(const file_status& s) noexcept;
  • 最常用函数之一
  • 特点:适用于大多数数据文件
  • 示例
    if (fs::is_regular_file("document.pdf")) {std::cout << "Regular file detected\n";
    }
    

is_symlink - 检查符号链接

bool is_symlink(const path& p);
bool is_symlink(const file_status& s) noexcept;
  • 注意:检查的是链接本身,不跟随链接
  • 示例
    fs::create_symlink("target.txt", "link.txt");
    if (fs::is_symlink("link.txt")) {  // 返回 truestd::cout << "This is a symbolic link\n";
    }
    

4. 状态检查函数

status_known - 检查状态是否已知

bool status_known(const file_status& s) noexcept;
  • 功能:检查 file_status 对象是否包含有效信息
  • 典型用途:缓存文件状态后验证有效性
  • 示例
    fs::file_status stat = fs::status("some_file");
    if (fs::status_known(stat)) {// 使用已知状态
    }
    

5. 性能优化建议

  1. 批量检查时缓存状态

    auto stat = fs::status(path);
    if (fs::is_regular_file(stat) && !fs::is_empty(stat)) {// 处理非空普通文件
    }
    
  2. 错误处理最佳实践

    std::error_code ec;
    bool is_dir = fs::is_directory("some_path", ec);
    if (ec) {// 处理错误(如路径不存在)
    }
    
  3. 符号链接处理注意

    // 检查符号链接本身
    bool is_link = fs::is_symlink("path");// 检查符号链接指向的目标
    bool is_target_dir = fs::is_directory(fs::read_symlink("path"));
    

6. 完整示例

#include <filesystem>
#include <iostream>
namespace fs = std::filesystem;void check_file_type(const fs::path& p) {std::error_code ec;auto stat = fs::symlink_status(p, ec);  // 不跟随符号链接if (ec) {std::cerr << "Error: " << ec.message() << "\n";return;}std::cout << p << " is:\n";if (fs::is_regular_file(stat)) std::cout << " - Regular file\n";if (fs::is_directory(stat)) std::cout << " - Directory\n";if (fs::is_symlink(stat)) std::cout << " - Symbolic link\n";if (fs::is_block_file(stat)) std::cout << " - Block device\n";if (fs::is_character_file(stat)) std::cout << " - Character device\n";if (fs::is_fifo(stat)) std::cout << " - FIFO/pipe\n";if (fs::is_socket(stat)) std::cout << " - Socket\n";if (fs::is_other(stat)) std::cout << " - Other type\n";if (fs::is_empty(p)) std::cout << " - Empty\n";
}int main() {check_file_type("/dev/sda");check_file_type("/tmp/mysocket");check_file_type("regular_file.txt");
}

这些类型检查函数为文件系统操作提供了必要的类型判别能力,是构建健壮的文件操作逻辑的基础。合理使用它们可以避免许多常见的文件操作错误。

http://www.lryc.cn/news/589338.html

相关文章:

  • 20250715正面看MIPI接口的LCD屏正常,侧面看发红是什么原因?
  • 12.6 Google黑科技GShard:6000亿参数MoE模型如何突破显存限制?
  • C++-linux系统编程 8.进程(三)孤儿进程、僵尸进程与进程回收
  • 算法学习笔记:22.贪心算法之霍夫曼编码 ——从原理到实战,涵盖 LeetCode 与考研 408 例题
  • 多相机depth-rgb图组完整性分拣器_MATLAB实现
  • 魔搭官方教程【快速开始】-swift 微调报错:`if v not in ALL_PARALLEL_STYLES`
  • 线上项目-升级redis8.0.3遇到的错
  • iOS高级开发工程师面试——关于网络
  • el-tooltip 快速滚动的时候出现残影如何解决 vue3
  • 学习嵌入式的第二十八天-数据结构-(2025.7.15)进程和线程
  • 20250715武汉xx公司面试一面
  • [AI-video] Web UI | Streamlit(py to web) | 应用配置config.toml
  • 索尼(SONY)摄像机mp4文件删除覆盖的恢复方法
  • 如何选择影视会员api接口?
  • 【字节跳动】数据挖掘面试题0019:带货直播间推荐:现在有一个带货的直播间,怎么把它精准地推送给有需要的用户
  • Flutter 入门指南:从基础到实战
  • 劳务派遣vs劳务外包:HR必懂的区别
  • 场景设计题+智力题
  • 《星盘接口9:永恒之门》
  • flutter下的webview适配rem问题
  • easy-springdoc
  • 手撕线程池详解(C语言源码+解析)
  • 35.KMP 算法
  • 分发糖果-leetcode
  • Python 字典 (Dictionary) 详解
  • JavaScript进阶篇——第三章 箭头函数核心
  • RabbitMQ第三章(企业级MQ应用方案)
  • AI大模型应用架构演进:从LLM基础到Agent协作的范式转移
  • 【SOA用于噪声抑制】光纤DFB激光器中弛豫振荡噪声抑制
  • IPsec:网络层的加密盾牌与HTTPS的差异解析