首页 > 编程语言 >C++17 Filesystem 实用教程

C++17 Filesystem 实用教程

时间:2025-01-16 16:21:39浏览次数:1  
标签:std 实用教程 fs cout 17 路径 C++ report path

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

    include

    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函数体, 读者可以从文末的源码链接获取完整源代码.

  1. 创建和删除目录

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

  2. 遍历目录

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

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

  1. 查询文件属性

    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";
    }

  2. 复制和重命名文件

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

  3. 处理符号链接

    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"

注意事项:

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

最佳实践

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

路径类型:
    使用 fs::absolute 将相对路径转换为绝对路径, 以确保路径的完整性和清晰性.

性能优化:
    对于网络磁盘或涉及大量文件的操作, 尽量减少 I/O 操作以提高性能.

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

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

路径规范化:
    使用 lexically_normal() 清理路径中的 . 和 .., 以获得更简洁的路径表示.

限制性

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

结论

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

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

到此这篇关于C++17 Filesystem 实用教程的文章就介绍到这了

标签:std,实用教程,fs,cout,17,路径,C++,report,path
From: https://www.cnblogs.com/Ryan9399/p/18675206

相关文章

  • 计算机毕业设计—311017 spring boot酒店预定系统(源码免费领)
    摘 要信息化社会内需要与之针对性的信息获取途径,但是途径的扩展基本上为人们所努力的方向,由于站在的角度存在偏差,人们经常能够获得不同类型信息,这也是技术最为难以攻克的课题。针对酒店客房预定等问题,对酒店信息管理进行研究分析,然后开发设计出酒店预订系统以解决问题。......
  • 【C++】开源:ImGui图形用户界面库配置与使用
    项目介绍项目Github地址:https://github.com/ocornut/imguiDearImGui(ImGui)是一个开源的、用C++编写的图形用户界面(GUI)库。它由OCornut创建,旨在为应用程序和工具提供创建用户界面的简单高效的方式。以下是DearImGui的一些主要特性和特点:1.即时模式GUI:ImGui遵循即......
  • c++基础算法讲解(写了ccf考试中可能出现的各种算法)
    枚举法枚举法是一种基本的问题解决策略,它尝试所有可能的情况以找到解决方案。这种方法通常用于问题规模较小且可以接受一定时间复杂度的情况。例子:找出三个数中最大的数#include<iostream>usingnamespacestd;intfindMax(inta,intb,intc){returnmax(a,......
  • 编译原理实验四----NFA确定化(附C++代码)
    编译原理实验四----NFA确定化(附C++代码)经验分享算法思路前述知识点输入结构体子集法(确定化)代码1:寻找闭包代码2:自动机运作总流程代码3:重新命名最小化代码本文仅为编译原理课程实验记录开发过程,设计的知识点,以及实现算法的设计过程使用的是Qt开发......
  • 来试试用c++来测出你的幸运值吧~~~(1.0版)(while循环)(好玩小游戏)
    你是不是也想知道自己的幸运值呢?来试试看吧!废话不多说,上代码!不要忘记点赞哦~~~#include<bits/stdc++.h>#include<windows.h>usingnamespacestd;voidmeasureLuck(intl){intn;cout<<"输入测幸运次数吧!:";cin>>n;cout<<"最大的和是"<&......
  • C/C++基础之sort排序
    sort(起始地址,结束地址的下一位,比较函数)注:比较函数可写可不写。默认sort函数是升序排序的。使用方法如下:#include<bits/stdc++.h>usingnamespacestd;intmain(){ inta[100]; intn;//数组的实际长度 ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);//取消同......
  • C++基础学习01
    C++基础学习012025-01-1611:29:04星期四首先是函数的结构,具体包括四个部分:返回值类型,函数名,形参列表和函数体接下来是输出输出流和C++标准库。我们要实现一个简单的A+B的输入输出,这里需要用到C++的iostream库,于是我们就需要使用cin和cout分别表示输入输出。然后是关于......
  • LeetCode 1773. 统计匹配检索规则的物品数量
    在这个问题中,我们被要求统计一个物品数组中满足特定检索规则的物品数量。每个物品由其类型、颜色和名称定义,而检索规则由规则键和规则值指定。我们的任务是找出数组中满足这些规则的物品数量。问题描述解题思路定义索引映射:首先,我们需要定义一个映射,将规则键("type"、"color......
  • 【Html.js——功能实现】新年贺卡(蓝桥杯真题-1768)【合集】
    目录......
  • 洛谷题单指南-线段树的进阶用法-P2617 Dynamic Rankings
    原题链接:https://www.luogu.com.cn/problem/P2617题意解读:动态求区间第k小问题。解题思路:树套树的典型应用,具体阐述参考:https://www.cnblogs.com/jcwy/p/18640914100分代码:#include<bits/stdc++.h>usingnamespacestd;constintN=100005;structOp{charop;......