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"
canonical
和 weakly_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"的绝对路径
relative
和 proximate
- 获取相对路径
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); // 设置当前工作目录
- 注意:设置工作目录影响整个进程
exists
和 equivalent
- 存在性检查
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. 删除和重命名
remove
和 remove_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) };
status
和 symlink_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
- Windows:
使用建议
-
错误处理:生产代码应使用
error_code
版本std::error_code ec; auto size = fs::file_size("file.txt", ec); if (ec) { /* 处理错误 */ }
-
跨平台注意:
- Windows路径大小写不敏感
- 符号链接行为可能不同
-
性能敏感场景:
// 避免重复状态检查 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. 性能优化建议
-
批量检查时缓存状态:
auto stat = fs::status(path); if (fs::is_regular_file(stat) && !fs::is_empty(stat)) {// 处理非空普通文件 }
-
错误处理最佳实践:
std::error_code ec; bool is_dir = fs::is_directory("some_path", ec); if (ec) {// 处理错误(如路径不存在) }
-
符号链接处理注意:
// 检查符号链接本身 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");
}
这些类型检查函数为文件系统操作提供了必要的类型判别能力,是构建健壮的文件操作逻辑的基础。合理使用它们可以避免许多常见的文件操作错误。