C++17 Filesystem 实用指南

news2025/1/8 10:22:25

C++17 标准带来了 std::filesystem库, 提供了强大的工具来处理文件路径, 目录以及其他与文件系统相关的操作. 这篇文章适合 C++ 初学者以及希望掌握 C++17 新特性的开发者, 旨在帮助他们高效地完成文件系统相关任务.


什么是 std::filesystem?

std::filesystem 是 C++ 标准库的一部分, 位于 std::filesystem 名称空间中. 它提供了一个平台独立的方式来与文件系统交互, 支持目录导航, 查询文件属性和实现文件操作等功能.


为什么使用 std::filesystem?

在 C++17 之前, 开发者依赖于平台特定的 API 或第三方库进行文件操作, 导致可移植性的挑战. 使用 std::filesystem, 您可以获得:

  • 跨平台支持: 为 Windows, Linux 和 macOS 提供统一的 API.
  • 便据性: 提供相关文件操作的直观函数.
  • 性能: 接口实现根据平台做了优化处理.

std::filesystem 常用功能

1. 检查文件和目录是否存在

#include <filesystem>
#include <iostream>

namespace fs = std::filesystem;

int main() {
  fs::path filePath = "example.txt";
  if (fs::exists(filePath)) {
    std::cout << "文件存在!\n";
  } else {
    std::cout << "文件不存在.\n";
  }
  return 0;
}

为了保持代码简洁, 后续代码中将不再包含头文件和main函数体, 读者可以从文末的源码链接获取完整源代码.

2. 创建和删除目录

fs::path dirPath = "new_directory";
fs::create_directory(dirPath);  // 创建单个目录
fs::remove(dirPath);            // 删除目录

3. 遍历目录

fs::path dirPath = "."; // 当前目录
for (const auto& entry : fs::recursive_directory_iterator(dirPath)) {
    std::cout << entry.path() << std::endl;
}

此示例会递归列出当前目录及其所有子目录中的文件和文件夹.

4. 查询文件属性

fs::path filePath = "example.txt";
if (fs::exists(filePath)) {
  std::cout << "文件大小: " << fs::file_size(filePath) << " 字节\n";
  std::cout << "是否为正解文件: " << fs::is_regular_file(filePath) << "\n";
  std::cout << "文件最后修改时间: "
            << fs::last_write_time(filePath).time_since_epoch().count()
            << "\n";
}

5. 复制和重命名文件

fs::copy("source.txt", "destination.txt", fs::copy_options::overwrite_existing); // 复制文件
fs::rename("old_name.txt", "new_name.txt"); // 重命名文件

6. 处理符号链接

fs::path symlinkPath = "symbolic_link";
fs::path targetPath = "target_file";
fs::create_symlink(targetPath, symlinkPath);  // 创建符号链接
if (fs::is_symlink(symlinkPath)) {
  std::cout << symlinkPath << " 是符号链接, 指向 "
            << fs::read_symlink(symlinkPath) << std::endl;
}

路径相关操作

7.1 路径组合

// 1. 路径组合
fs::path base = "/home/user/documents";
fs::path file = "report.pdf";
fs::path fullPath = base / file;  // 使用 / 操作符组合路径
std::cout << "组合路径: " << fullPath << std::endl;

输出

组合路径: "/home/user/documents/report.pdf"

7.2 获取路径组件

fs::path filepath = "/home/user/documents/report.pdf";
std::cout << "文件名: " << filepath.filename() << std::endl;
std::cout << "主文件名: " << filepath.stem() << std::endl;
std::cout << "扩展名: " << filepath.extension() << std::endl;
std::cout << "父路径: " << filepath.parent_path() << std::endl;

输出

文件名: "report.pdf"
主文件名: "report"
扩展名: ".pdf"
父路径: "/home/user/documents"

7.3 相对路径计算

fs::path p1 = "/home/user/documents";
fs::path p2 = "/home/user/pictures";
fs::path rel = fs::relative(p2, p1);  // 计算从 p1 到 p2 的相对路径
std::cout << "相对路径: " << rel << std::endl;  // ../pictures

输出

相对路径: "../pictures"

7.4 路径分解与迭代

fs::path complex = "/home/user/documents/work/report.pdf";
std::cout << "路径分解:" << std::endl;
for (const auto& part : complex) {
  std::cout << "  " << part << std::endl;
}

输出

路径分解:
  "/"
  "home"
  "user"
  "documents"
  "work"
  "report.pdf"

7.5 词法规范化路径

fs::path messy = "home/user/../user/./documents/report.pdf";
std::cout << "规范化路径: " << messy.lexically_normal() << std::endl;

输出

规范化路径: "home/user/documents/report.pdf"

7.6 路径比较

// 使用 std::filesystem::equivalent 检查两个路径是否指向同一文件
fs::path linkPath =
    "link_to_report.pdf";  // 假设这是一个指向 report.pdf 的符号链接
fs::path actualPath = "documents/report.pdf";
try {
  if (fs::equivalent(linkPath, actualPath)) {
    std::cout << "路径 " << linkPath << " 和 " << actualPath
              << " 指向同一文件." << std::endl;
  } else {
    std::cout << "路径 " << linkPath << " 和 " << actualPath
              << " 不指向同一文件." << std::endl;
  }
} catch (const fs::filesystem_error& e) {
  std::cerr << "文件系统错误: " << e.what() << std::endl;
}
7.7 路径拼接
fs::path prefix = "backup_";
fs::path filename = "report.pdf";
fs::path newPath = prefix.string() + filename.string();
std::cout << "拼接路径: " << newPath << std::endl;

输出

拼接路径: "backup_report.pdf"
7.8 检查路径特性
fs::path checkPath = "/home/user/documents/report.pdf";
std::cout << "是否为绝对路径: " << checkPath.is_absolute() << std::endl;
std::cout << "是否有扩展名: " << checkPath.has_extension() << std::endl;
std::cout << "是否有文件名: " << checkPath.has_filename() << std::endl;
std::cout << "是否有父路径: " << checkPath.has_parent_path() << std::endl;

输出

是否为绝对路径: 1
是否有扩展名: 1
是否有文件名: 1
是否有父路径: 1

路径替换操作

fs::path modPath = "/home/user/documents/report.pdf";
modPath.replace_filename("newreport.doc");
std::cout << "替换文件名后: " << modPath << std::endl;
modPath.replace_extension(".txt");
std::cout << "替换扩展名后: " << modPath << std::endl;

输出

替换文件名后: "/home/user/documents/newreport.doc"
替换扩展名后: "/home/user/documents/newreport.txt"

注意事项:

  1. 路径操作是纯字符串操作, 不涉及实际文件系统
  2. 这些操作在 Windows 和 Unix 系统上都能正常工作
  3. 使用 / 操作符组合路径比直接字符串拼接更安全
  4. lexically_normal() 可以清理路径中的 ...

最佳实践

  1. 错误处理:

    • 使用异常处理来捕获和管理错误情况. 许多 std::filesystem 函数会抛出 std::filesystem::filesystem_error, 例如在没有删除权限时.
  2. 路径类型:

    • 使用 fs::absolute 将相对路径转换为绝对路径, 以确保路径的完整性和清晰性.
  3. 性能优化:

    • 对于网络磁盘或涉及大量文件的操作, 尽量减少 I/O 操作以提高性能.
  4. 跨平台注意事项:

    • 路径格式: 虽然 std::filesystem 自动处理不同平台的路径分隔符差异(Windows 使用 \, 其他平台使用 /), 但建议始终使用 fs::path 进行路径操作.
    • 文件权限: 不同平台的文件权限管理可能不一致, 尤其是 fs::permissions.
  5. 路径组合:

    • 使用 / 操作符组合路径比直接字符串拼接更安全.
  6. 路径规范化:

    • 使用 lexically_normal() 清理路径中的 ..., 以获得更简洁的路径表示.

限制性

  • 调用链接文件: 包含链接文件的操作在不同平台上有不同表现.
  • 性能: 尽管高效, 部分文件系统操作在网络磁盘上仍会突出慢.

结论

std::filesystem 库是 C++ 重要的增加, 使文件和目录操作更加简单和可移植. 无论您是在写一个简单脚本, 还是构建复杂应用, 熟练该库都是值得一试的.

开始探索 std::filesystem, 你将发现它是你 C++ 程序装备中一个珍贵的工具!


资源链接

  • 官方文档
  • 微软教程

源码链接

源码链接

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2273153.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

下载b站高清视频

需要使用的edge上的一个扩展插件&#xff0c;所以选择使用edge浏览器。 1、在edge浏览器上下载 强力视频下载合并 扩展插件 2、在edge上打开b站&#xff0c;登录自己账号&#xff08;登录后才能下载到高清&#xff01;&#xff01;&#xff09;。打开一个视频&#xff0c;选择自…

flutter 专题二十四 Flutter性能优化在携程酒店的实践

Flutter性能优化在携程酒店的实践 一 、前言 携程酒店业务使用Flutter技术开发的时间快接近两年&#xff0c;这期间有列表页、详情页、相册页等页面使用了Flutter技术栈进行了跨平台整合&#xff0c;大大提高了研发效率。在开发过程中&#xff0c;也遇到了一些性能相关问题和…

UE5 打包要点

------------------------- 1、需要环境 win sdk &#xff0c;大约3G VS&#xff0c;大约10G 不安装就无法打包&#xff0c;就是这么简单。 ----------------------- 2、打包设置 编译类型&#xff0c;开发、调试、发行 项目设置-地图和模式&#xff0c;默认地图 项目…

vulnhub靶场【DC系列】之5

前言 靶机&#xff1a;DC-5&#xff0c;IP地址为192.168.10.4 攻击&#xff1a;kali&#xff0c;IP地址为192.168.10.2 都采用VMWare&#xff0c;网卡为桥接模式 对于文章中涉及到的靶场以及工具&#xff0c;我放置网盘中https://pan.quark.cn/s/2fcf53ade985 主机发现 使用…

双模态视觉特征流用于医学报告生成|文献速递-视觉大模型医疗图像应用

Title 题目 Dual-modality visual feature flow for medical report generation 双模态视觉特征流用于医学报告生成 01 文献速递介绍 医学报告生成是一项新兴的跨模态文本生成任务&#xff08;X. Zeng et al., 2020&#xff1b;Najdenkoska et al., 2022&#xff1b;Li et…

基于Fluent和深度学习算法驱动的流体力学计算与应用

物理模型与深度学习的融合&#xff1a;研究如何将传统的物理模型与深度学习算法相结合&#xff0c;以提高流体力学问题的预测准确性和计算效率。复杂流动模拟&#xff1a;利用深度学习技术对复杂流动现象进行模拟和分析&#xff0c;包括湍流、多相流、非牛顿流体等&#xff0c;…

记PasteSpider部署工具的Windows.IIS版本开发过程之草稿-动态表单(2)

接1的内容&#xff0c;那么有这么一个需求&#xff01; 需求分析 需要修改某一个配置的时候 1.从对应的api中读取消息&#xff0c;消息内容为Json格式的 2.基于当前的Json渲染成表单提供给管理端的客户呈现 3.管理端的用户可以基于这个表单的内容进行修改&#xff0c;然后提交…

pycharm-pyspark 环境安装

1、环境准备&#xff1a;java、scala、pyspark、python-anaconda、pycharm vi ~/.bash_profile export SCALA_HOME/Users/xunyongsun/Documents/scala-2.13.0 export PATH P A T H : PATH: PATH:SCALA_HOME/bin export SPARK_HOME/Users/xunyongsun/Documents/spark-3.5.4-bin…

Clisoft SOS设置Workarea

Clisoft SOS设置Workarea 本人也是刚刚接触这个软件&#xff0c;可能有些方面不够完善&#xff0c;欢迎大佬指点。 这里就不演示创建创建Server和Project&#xff0c;可以参考Clisoft SOS设置Server和Project 创建Workarea 创建好目录并设置好权限 # 创建组 [bhlumaster ~]$…

数据结构:LinkedList与链表—无头双向链表(二)

目录 一、什么是LinkedList&#xff1f; 二、LinkedList的模拟实现 1、display()方法 2、addFirst(int data)方法 3、addLast(int data)方法 4、addIndex(int index,int data)方法 5、contains(int key)方法 6、remove(int key)方法 7、removeAllKey(int key)方法 8、…

基于SpringBoot实现的保障性住房管理系统

&#x1f942;(❁◡❁)您的点赞&#x1f44d;➕评论&#x1f4dd;➕收藏⭐是作者创作的最大动力&#x1f91e; &#x1f496;&#x1f4d5;&#x1f389;&#x1f525; 支持我&#xff1a;点赞&#x1f44d;收藏⭐️留言&#x1f4dd;欢迎留言讨论 &#x1f525;&#x1f525;&…

【Linux】硬链接和软连接(符号连接)

目录 硬链接 软连接 硬链接和软连接的区别 硬链接 ln根据linux系统分配给文件inode(ls -li)进行建立&#xff0c;没办法跨越文件系统 格式&#xff1a;ln 被链接的文件(源文件) 生成的链接文件(目标文件) 1) 硬链接的属性 - 相当于生成一个副本 起别名 2) 修改内容都变化…

多目标优化算法——基于聚类的不规则Pareto前沿多目标优化自适应进化算法(CA-MOEA)

基于聚类的不规则Pareto前沿多目标优化自适应进化算法&#xff08;CA-MOEA&#xff09; 一、算法简介 简介&#xff1a; 现有的多目标进化算法&#xff08;moea&#xff09;在具有规则Pareto前沿且Pareto最优解在目标空间上连续分布的多目标优化问题&#xff08;MOPs&#xff…

基于SpringBoot的乐器商城购物推荐系统

作者&#xff1a;计算机学姐 开发技术&#xff1a;SpringBoot、SSM、Vue、MySQL、JSP、ElementUI、Python、小程序等&#xff0c;“文末源码”。 专栏推荐&#xff1a;前后端分离项目源码、SpringBoot项目源码、Vue项目源码、SSM项目源码、微信小程序源码 精品专栏&#xff1a;…

【vba源码】自动获取汇率

Hi&#xff0c;大家好&#xff01; 没有想到今天居然是腊八&#xff0c;过了腊八就是年&#xff0c;离过年越来越近了&#xff0c;那在这里给大家就拜个年&#xff0c;希望大家在新的一年都有好事发生。 最近在弄点小项目&#xff0c;在项目遇到了一个汇率计算的问题&#xff…

JavaEE初阶——计算机工作原理

一、什么是JavaEE JavaEE&#xff08;Java Platform&#xff0c;Enterprise Edition&#xff09;是sun公司&#xff08;2009年4月20日甲骨文将其收购&#xff09;推出的企业级应用程序版本。这个版本以前称为 J2EE。能够帮助我们开发和部署可移植、健壮、可伸缩且安全的服务器…

【Unity3D】AB包加密(AssetBundle加密)

加密前&#xff1a; 加密后&#xff0c;直接无法加载ab&#xff0c;所以无法正常看到ab内容。 using UnityEngine; using UnityEditor; using System.IO; public static class AssetBundleDemoTest {[MenuItem("Tools/打包!")]public static void Build(){//注意:St…

数据库语句学习

WHERE AND: 请编写 SQL 语句&#xff0c;从 courses 表中&#xff0c;选取课程名为 Web 或者 Big Data 的课程信息&#xff0c;如果这两门课程存在&#xff0c;请将这两门课程的信息全部返回。 SELECT * FROM courses where name in (Web,Big Data) -- 等同于 -- WHERE name …

“AI智慧语言训练系统:让语言学习变得更简单有趣

大家好&#xff0c;我是你们的老朋友&#xff0c;一个热衷于探讨科技与教育结合的产品经理。今天&#xff0c;我想和大家聊聊一个让语言学习变得不再头疼的话题——AI智慧语言训练系统。这个系统可是我们语言学习者的福音&#xff0c;让我们一起来揭开它的神秘面纱吧&#xff0…

Postman接口测试05|实战项目笔记

目录 一、项目接口概况 二、单接口测试-登录接口&#xff1a;POST 1、正例 2、反例 ①姓名未注册 ②密码错误 ③姓名为空 ④多参 ⑤少参 ⑥无参 三、批量运行测试用例 四、生成测试报告 1、Postman界面生成 2、Newman命令行生成 五、token鉴权&#xff08;“…