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

C++17中头文件filesystem的使用

      C++17引入了std::filesystem库(文件系统库, filesystem library),相关类及函数的声明在头文件filesystem中,命名空间为std::filesystem。

      1.path类:文件路径相关操作,如指定的路径是否存在等,其介绍参见:https://blog.csdn.net/fengbingchun/article/details/133217504
      2.directory_entry类:获取文件属性等,如指定文件是否是常规文件,还包括文件大小、文件最后修改时间,其介绍参见:https://blog.csdn.net/fengbingchun/article/details/133430293
      3.directory_iterator类:遍历目录,获取目录文件,不包括子目录,其介绍参见:https://blog.csdn.net/fengbingchun/article/details/133437356
      4.recursive_directory_iterator类:遍历目录,获取目录文件,包括子目录,其介绍参见:https://blog.csdn.net/fengbingchun/article/details/133437356
      5.filesystem_error类:异常类,继承自std::system_error,继承关系如下图所示:

      (1).path1, path2:返回存储在异常对象中的path;
      (2).what: 返回解释性字符串;
      (3).code: 返回错误码。

      测试代码如下所示:

int test_filesystem_filesystem_error()
{// path1, path2, whtat// creates a unique filename that does not name a currently existing fileconst fs::path oldp{ std::tmpnam(nullptr) }, newp{ std::tmpnam(nullptr) };/* windows:what():  rename: 系统找不到指定的文件。: "C:\Users\f06190\AppData\Local\Temp\sf2w.0", "C:\Users\f06190\AppData\Local\Temp\sf2w.1"path1(): "C:\\Users\\f06190\\AppData\\Local\\Temp\\sf2w.0"path2(): "C:\\Users\\f06190\\AppData\\Local\\Temp\\sf2w.1" *//* linuxwhat():  filesystem error: cannot rename: No such file or directory [/tmp/filezJrUkO] [/tmp/filey7tqKV]path1(): "/tmp/filezJrUkO"path2(): "/tmp/filey7tqKV" */try {fs::rename(oldp, newp); // throws since oldp does not exist} catch (fs::filesystem_error const& ex) {std::cout << "what():  " << ex.what() << '\n'<< "path1(): " << ex.path1() << '\n'<< "path2(): " << ex.path2() << '\n';}return 0;
}

      6.file_status类:获取或设置有关文件类型(type)和权限(permissions)的信息
      (1).type: 获取或设置文件类型信息;
      (2).permissions: 获取或设置文件权限信息。

      测试代码如下所示:

void demo_status(const fs::path& p, fs::file_status s)
{std::cout << p;switch (s.type()) {case fs::file_type::none:std::cout << " has `not-evaluated-yet` type";break;case fs::file_type::not_found:std::cout << " does not exist";break;case fs::file_type::regular:std::cout << " is a regular file";break;case fs::file_type::directory:std::cout << " is a directory";break;case fs::file_type::symlink:std::cout << " is a symlink";break;case fs::file_type::block:std::cout << " is a block device";break;case fs::file_type::character:std::cout << " is a character device";break;case fs::file_type::fifo:std::cout << " is a named IPC pipe";break;case fs::file_type::socket:std::cout << " is a named IPC socket";break;case fs::file_type::unknown:std::cout << " has `unknown` type";break;default:std::cout << " has `implementation-defined` type";break;}std::cout << '\n';
}void demo_perms(fs::perms p)
{using fs::perms;auto show = [=](char op, perms perm) {std::cout << (perms::none == (perm & p) ? '-' : op);};show('r', perms::owner_read);show('w', perms::owner_write);show('x', perms::owner_exec);show('r', perms::group_read);show('w', perms::group_write);show('x', perms::group_exec);show('r', perms::others_read);show('w', perms::others_write);show('x', perms::others_exec);std::cout << '\n';
}int test_filesystem_file_status()
{
#ifdef _MSC_VERconst std::string path{ "../../../testdata/list.txt" };
#elseconst std::string path{ "../../testdata/list.txt" };
#endif// 1. type// windows: "../../../testdata/list.txt" is a regular file// linux: "../../testdata/list.txt" is a regular filedemo_status(path, fs::status(path));// 2. permissionsdemo_perms(fs::status(path).permissions()); // rwxrwxrwxreturn 0;
}

      7.space_info结构体:获取有关文件系统上的空闲(free)和可用空间(available space)的信息

struct space_info {std::uintmax_t capacity; // 总大小,以字节为单位std::uintmax_t free; // 可用空间,以字节为单位std::uintmax_t available; // 非特权进程可用的可用空间(可能等于或小于可用空间)
};
float get_file_size(std::uintmax_t size, std::string& suffix)
{float s1 = size / 1024. / 1024 / 1024;float s2 = size / 1024. / 1024;float s3 = size / 1024.;if (s1 > 1) {suffix = " GB";return s1;}if (s2 > 1) {suffix = " MB";return s2;}if (s3 > 1) {suffix = " KB";return s3;}suffix = " Bytes";return size;
}int test_filesystem_space_info()
{fs::space_info info = fs::space(fs::current_path());std::cout << "current path: " << fs::current_path() << "  ";// windows: current path: "E:\\GitCode\\Messy_Test\\prj\\x86_x64_vc12\\CppBaseTest"   size: 311.00 GB   size: 189.23 GB   size: 189.23 GB// linux: current path: "/home/spring/GitCode/Messy_Test/prj/linux_cmake_CppBaseTest"   size: 311.00 GB   size: 189.23 GB   size: 189.23 GBfor (auto x : { info.capacity, info.free, info.available }) {std::string suffix;auto value = get_file_size(static_cast<std::intmax_t>(x), suffix);std::cout << " size: " << std::fixed << std::setprecision(2) << value << suffix << "  ";}std::cout << std::endl;return 0;
}

      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枚举类:文件访问权限,如下图所示

      10.perm_options枚举类:控制函数std::filesystem::permissions()行为的可用选项,如下图所示:

enum class perm_options {replace = /* unspecified */,add = /* unspecified */,remove = /* unspecified */,nofollow = /* unspecified */
};

      11.非成员函数:
      (1).absolute:返回绝对路径;
      (2).canonical, weakly_canonical: 将指定路径转换为规范绝对路径(canonical absolute path),指定的路径必须存在;
      (3).relative, proximate: 返回相对路径;
      (4).copy: 拷贝文件或目录,会生成新的文件或目录,from指定的文件或目录必须存在,to指定的文件或目录必须不存在;
      (5).copy_file: 拷贝文件,会生成新的文件,from指定的文件必须存在,to指定的文件必须不存在;若发生错误,则返回false;
      (6).copy_symlink:拷贝符号链接;
      (7).create_directory, create_directories: 创建新目录,使用create_directory时要求父目录必须已存在,即create_directory不支持多级创建,而create_directories没有这些限制;
      (8).create_hard_link:创建硬链接;
      (9).create_symlink, create_directory_symlink: 创建符号链接;
      (10).current_path: 获取当前工作目录
      (11).exists: 检查指定的文件或目录是否存在
      (12).equivalent: 检查两个路径是否是相同的;
      (13).file_size: 获取文件大小
      (14).hard_link_count: 获取指定路径硬链接数;
      (15).last_write_time: 获取或设置指定路径最后一次修改时间
      (16).permissions: 修改文件访问权限;
      (17).read_symlink: 获取符号链接的target;
      (18).remove, remove_all:删除文件或空目录;remove_all可递归地删除文件或目录及其所有内容并返回已删除的文件和目录的数量;
      (19).rename: 重命名文件或目录
      (20).resize_file: 更改常规文件大小;
      (21).space: 获取指定的路径的可用空间
      (22).status, symlink_status: 获取文件属性,如指定路径是否是常规文件、是否是目录等;
      (23).temp_directory_path: 返回适合临时文件的目录
      std::error_code类是与平台相关的错误码。std::filesystem中的所有函数都有一个对应非抛出异常的对等接口

      测试代码如下所示:

int test_filesystem_non_member_functions()
{const fs::path p1 = "../funset.cpp";
#ifdef _MSC_VERconst fs::path p2{ "../../../testdata/list.txt" }, p3{ "../../../testdata/list_copy.txt" }, p4{ "E:\\yulong.mp4" }, p5{ "../../../testdata/list_new.txt" };
#elseconst fs::path p2{ "../../testdata/list.txt" }, p3{ "../../testdata/list_copy.txt" }, p4{ "./build/CppBaseTest" }, p5{"../../testdata/list_new.txt"};
#endif// windows: current path is "E:\\GitCode\\Messy_Test\\prj\\x86_x64_vc12\\CppBaseTest"// linux: current path is "/home/spring/GitCode/Messy_Test/prj/linux_cmake_CppBaseTest"std::cout << "current path is " << fs::current_path() << '\n';// 1. absolute// windows: absolute path for "../funset.cpp" is "E:\\GitCode\\Messy_Test\\prj\\x86_x64_vc12\\funset.cpp"// linux: absolute path for "../funset.cpp" is "/home/spring/GitCode/Messy_Test/prj/linux_cmake_CppBaseTest/../funset.cpp"std::cout << "absolute path for " << p1 << " is " << fs::absolute(p1) << '\n';// 2. canonical, weakly_canonical/* windows:canonical path: "E:\\GitCode\\Messy_Test\\testdata\\list.txt"weakly canonical path: "E:\\GitCode\\Messy_Test\\testdata\\list.txt" *//* linux:canonical path: "/home/spring/GitCode/Messy_Test/testdata/list.txt"weakly canonical path: "/home/spring/GitCode/Messy_Test/testdata/list.txt" */std::cout << "canonical path: " << fs::canonical(p2) << "\n";std::cout << "weakly canonical path: " << fs::weakly_canonical(p2) << "\n";// 3. relative, proximatestd::cout << "relative path: " << fs::relative("/a/b/c", "/a/b")<< ", proximat path: " << fs::proximate("/a/b/c", "/a/b") << "\n";	// relative path: "c", proximat path: "c"// 4. copy, exists, removeif (fs::exists(p3))fs::remove(p3);fs::copy(p2, p3);// 5. copy_fileif (fs::exists(p3))fs::remove(p3);fs::copy_file(p2, p3);// 6. create_directory, create_directoriesfs::create_directory("./a");fs::create_directories("./b/c/d");// 7. equivalentif (fs::equivalent(".", fs::current_path()))std::cout << "they are equal" << "\n";// 8. file_sizestd::string suffix;auto value = get_file_size(static_cast<std::intmax_t>(fs::file_size(p4)), suffix);// windows: size: 1.35 GB; linux: size: 7.61 MBstd::cout << "size: " << std::fixed << std::setprecision(2) << value << suffix << "\n";// 9. last_write_time// windows: last write time: 2023-08-19 22:42:56// linux: last write time: 2023-10-03 12:32:49std::cout << "last write time: " << to_time_t(last_write_time(p4)) << std::endl;// 10. permissions// windows: rwxrwxrwx r-xr-xr-x// linux:   rw-rw-r-- -w-r-----demo_perms(fs::status(p3).permissions());
#ifdef _MSC_VERfs::permissions(p3, fs::perms::none);
#elsefs::permissions(p3, fs::perms::owner_write | fs::perms::group_read);
#endifdemo_perms(fs::status(p3).permissions());// 11. renameif (fs::exists(p5))fs::remove(p5);fs::rename(p3, p5);// 12. resize_file// linux: size: 187.00 Bytes  size: 64.00 KBvalue = get_file_size(static_cast<std::intmax_t>(fs::file_size(p5)), suffix);std::cout << "size: " << std::fixed << std::setprecision(2) << value << suffix << "\n";
#ifdef __linux__fs::resize_file(p5, 64 * 1024); // resize to 64 KB, windows crashvalue = get_file_size(static_cast<std::intmax_t>(fs::file_size(p5)), suffix);std::cout << "size: " << std::fixed << std::setprecision(2) << value << suffix << "\n";
#endif// 13. temp_directory_path// windows: temp directory is: "C:\\Users\\f06190\\AppData\\Local\\Temp\\"// linux: temp directory is: "/tmp"std::cout << "temp directory is: " << fs::temp_directory_path() << "\n";// std::error_codestd::error_code ec;fs::copy_file("xxx", "yyy", ec); // does not throw// windows: error code: 2,系统找不到指定的文件。// linux: error code: 2,No such file or directorystd::cout << "error code: " << ec.value() << "," << ec.message() << "\n";try {fs::copy_file("xxx", "yyy");} catch (fs::filesystem_error const& ex) {std::cout << "what():  " << ex.what() << '\n'<< "path1(): " << ex.path1() << '\n'<< "path2(): " << ex.path2() << '\n'<< "code().value():    " << ex.code().value() << '\n'<< "code().message():  " << ex.code().message() << '\n'<< "code().category(): " << ex.code().category().name() << '\n';}return 0;
}

      执行结果如下图所示:

      12.文件类型:
      (1).is_block_file: 检查给定的文件或路径是否是块设备;
      (2).is_character_file: 检查给定的文件或路径是否是字符设备;
      (3).is_directory: 检查给定的文件或路径是否是目录
      (4).is_empty: 检查给定的文件或路径是否是空文件或空目录
      (5).is_fifo: 检查给定的文件或路径是否是命名管道;
      (6).is_other: 检查给定的文件或路径是否是其它文件;
      (7).is_regular_file: 检查给定的文件或路径是否是常规文件
      (8).is_socket: 检查给定的文件或路径是否是套接字;
      (9).is_symlink: 检查给定的文件或路径是否是符号链接;
      (10).status_known: 检查给定的文件是否已知。

      测试代码如下所示:

void demo_status2(const fs::path& p, fs::file_status s)
{std::cout << p;// alternative: switch(s.type()) { case fs::file_type::regular: ...}if (fs::is_regular_file(s))std::cout << " is a regular file\n";if (fs::is_directory(s))std::cout << " is a directory\n";if (fs::is_block_file(s))std::cout << " is a block device\n";if (fs::is_character_file(s))std::cout << " is a character device\n";if (fs::is_fifo(s))std::cout << " is a named IPC pipe\n";if (fs::is_socket(s))std::cout << " is a named IPC socket\n";if (fs::is_symlink(s))std::cout << " is a symlink\n";if (!fs::exists(s))std::cout << " does not exist\n";//if (fs::is_empty(p))//	std::cout << " is empty\n";if (fs::is_other(s)) // equivalent to exists(s) && !is_regular_file(s) && !is_directory(s) && !is_symlink(s)std::cout << " is other file\n";//if (fs::status_known(s)) // equivalent to s.type() != file_type::none//	std::cout << " is status known\n";
}int test_filesystem_file_types()
{demo_status2("/dev/null", fs::status("/dev/null"));demo_status2("/dev/sda", fs::status("/dev/sda"));demo_status2(fs::current_path(), fs::status(fs::current_path()));demo_status2("/xxx/yyy", fs::status("/xxx/yyy"));demo_status2("/usr/bin/g++", fs::status("usr/bin/g++"));demo_status2("../../../testdata/list.txt", fs::status("../../../testdata/list.txt"));demo_status2("../../testdata/list.txt", fs::status("../../testdata/list.txt"));demo_status2("/mnt", fs::status("/mnt"));return 0;
}

      GitHub:https://github.com/fengbingchun/Messy_Test

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

相关文章:

  • 「专题速递」数字人直播带货、传统行业数字化升级、远程协作中的低延时视频、地产物业中的通讯终端...
  • PE格式之PE头部
  • SLAM从入门到精通(用python实现机器人运动控制)
  • 接口和抽象类有什么区别?
  • 基于springboot+vue的人事系统
  • 记住这份软件测试八股文还怕不能拿offer?你值得拥有
  • 2023年,在CSDN拥有10000粉丝有多难?
  • C++ -- 学习系列 关联式容器 set 与 map
  • Day 04 python学习笔记
  • Moonbeam Ignite强势回归
  • 【改造后序遍历算法】95. 不同的二叉搜索树 II
  • 栈的基本操作(数据结构)
  • D. Jellyfish and Mex Codeforces Round 901 (Div. 2)
  • 操作系统内存管理相关
  • Sui流动性质押黑客松获胜者公布,助力资产再流通
  • 为什么在使用PageHelper插件时,指定的每页记录数大小失效?显示所有的记录数
  • XML文档基础
  • 软考知识汇总-软件工程
  • 力扣:119. 杨辉三角 II(Python3)
  • 指针笔试题(带解析版)
  • 服务器搭建(TCP套接字)-libevent版(服务端)
  • 斐波那契模型系列【动态规划】
  • 【Java】微服务——Nacos注册中心
  • Redis Cluster Gossip Protocol: PING, PONG, MEET
  • httpserver 下载服务器demo 以及libevent版本的 httpserver
  • 构建强大的RESTful API:@RestController与@Controller的对比与应用
  • 【Java-LangChain:使用 ChatGPT API 搭建系统-10】评估(下)-当不存在一个简单的正确答案时
  • 【微服务的集成测试】python实现-附ChatGPT解析
  • Mesa新版来袭
  • 基于 SpringBoot 2.7.x 使用最新的 Elasticsearch Java API Client 之 ElasticsearchClient