C++20中filesystem庫的使用
一、filesystem 介紹
filesystem 源自boost.filesystem庫,在C++17合并進(jìn)C++標(biāo)準(zhǔn)庫中,filesystem中的所有操作是線程不安全的。
二、路徑相關(guān)操作
在filesystem庫中提供path類來對(duì)路徑進(jìn)行操作,后續(xù)的相關(guān)操作,如打開文件、遍歷目錄、判斷文件類型等,都是需要用path作為參數(shù)來指定操作具體路徑。
2.1 path 初始化
#include <filesystem>
#include <iostream>
namespace fs = std::filesystem;
int main()
{
fs::path p; //empty path
fs::path p1 = "/usr/lib/sendmail.cf"; // portable format
fs::path p2 = p1; // copy construct
fs::path p3 = std::move(p1); // move construct
std::cout << "p = " << p << '\n'
<< "p1 = " << p1 << '\n'
<< "p2 = " << p2 << '\n'
<< "p3 = " << p3 << '\n';
}
output:
p = "" p1 = "" /// 被移動(dòng)后p1 變成空路徑 p2 = "/usr/lib/sendmail.cf" p3 = "/usr/lib/sendmail.cf"
2.2 path 路徑拼接操作
常見操作目錄路徑+文件名拼接成完成文件路徑
path += 和 / 操作
#include <filesystem>
#include <iostream>
namespace fs = std::filesystem;
int main()
{
fs::path p1 = "/usr/lib/";
fs::path p2 = "/usr/lib";
fs::path p3 = p1 / "text.txt";
fs::path p4 = p2 / "text.txt"; //會(huì)添加反斜杠
p1 += "text.txt";
p2 += "text.txt"; //不會(huì)添加反斜杠,操作更類似字符串拼接
std::cout << "p1 = " << p1 << '\n'
<< "p2 = " << p2 << '\n'
<< "p3 = " << p3 << '\n'
<< "p3 = " << p4 << '\n';
}
output:
(注意p2的路徑輸出是沒有/usr/lib和text.txt之間是沒反斜桿的)
p1 = "/usr/lib/text.txt" p2 = "/usr/libtext.txt" p3 = "/usr/lib/text.txt" p3 = "/usr/lib/text.txt"
2.3 對(duì)路徑文件名進(jìn)行操作修改
#include <filesystem>
#include <iostream>
namespace fs = std::filesystem;
int main()
{
fs::path p = "foo/bar/old.txt";
//判斷是否存在文件名
if(p.has_filename())
std::cout << p.filename() << std::endl; //old.txt
/// 替換文件名
p.replace_filename("new.txt");
std::cout << p.filename() << std::endl;
/// 刪除文件名
p.remove_filename();
std::cout << std::boolalpha << p.has_filename() << std::endl; /// false
return 0;
}
output:
"old.txt" "new.txt" false
2.4 對(duì)文件拓展名修改
#include <filesystem>
#include <iostream>
namespace fs = std::filesystem;
int main()
{
fs::path p = "foo/bar/old.txt";
fs::path p1 = "foo/bar";
std::cout << std::boolalpha << p.has_extension()
<< " " << p1.has_extension() << std::endl;
//獲取拓展名
std::cout << "p extension " << p.extension() << std::endl;
//替換拓展名
p.replace_extension("png");
std::cout << "replace png " << p << std::endl;
//刪除拓展名
p.replace_extension("");
std::cout << "del extension " << p << std::endl;
//添加拓展名
p.replace_extension(".txt");
std::cout << "add extension .txt "<< p << std::endl;
return 0;
}
2.5 path 判斷路徑是否存在
#include <cstdint>
#include <filesystem>
#include <fstream>
#include <iostream>
namespace fs = std::filesystem;
int main()
{
const fs::path sandbox{"sandbox"};
fs::create_directory(sandbox);
std::ofstream{sandbox/"file"}; // create regular file
std::cout << std::boolalpha << fs::exists(sandbox) << std::endl; //true 目錄路徑
std::cout << std::boolalpha << fs::exists(sandbox/"file") << std::endl; //true 文件路徑
//不存在路徑
std::cout << std::boolalpha << fs::exists("/asd/asda") << std::endl;//false
fs::remove_all(sandbox);
}
三、目錄相關(guān)操作
3.1 創(chuàng)建目錄和刪除目錄
#include <cstdlib>
#include <filesystem>
#include <fstream>
#include <iostream>
namespace fs = std::filesystem;
int main()
{
//設(shè)置當(dāng)前路徑 為 /tmp
//相當(dāng)于 cd /tmp
fs::current_path(fs::temp_directory_path());
//mkdir -p sandbox/1/2/a 遞歸創(chuàng)建目錄
fs::create_directories("./sandbox/1/2/a");
//mkdir sandbox/1/2/b 創(chuàng)建目錄
fs::create_directory("./sandbox/1/2/b");
fs::permissions("./sandbox/1/2/b", fs::perms::others_all, fs::perm_options::remove);
//復(fù)制目錄屬性
fs::create_directory("./sandbox/1/2/c", "./sandbox/1/2/b");
std::system("ls -l sandbox/1/2");
std::system("tree sandbox");
//rm -rf sandbox
fs::remove_all("sandbox");
}
output:
total 12
drwxr-xr-x 2 cyy cyy 4096 Dec 19 13:09 a
drwxr-x--- 2 cyy cyy 4096 Dec 19 13:09 b
drwxr-x--- 2 cyy cyy 4096 Dec 19 13:09 c
sandbox
└── 1
└── 2
├── a
├── b
└── c
5 directories, 0 files3.2 遍歷指定目錄所有內(nèi)容,不包含".“和”…"
int main()
{
const std::filesystem::path sandbox{"sandbox"};
std::filesystem::create_directories(sandbox/"dir1"/"dir2");
std::ofstream{sandbox/"file1.txt"};
std::ofstream{sandbox/"file2.txt"};
//非遞歸遍歷該目錄下的內(nèi)容
std::cout << "directory_iterator:\n";
// directory_iterator can be iterated using a range-for loop
for (auto const& dir_entry : std::filesystem::directory_iterator{sandbox})
std::cout << dir_entry.path() << '\n';
//遞歸遍歷該目錄下所有內(nèi)容
std::cout << "\nrecursive_directory_iterator:\n";
for (auto const& dir_entry : std::filesystem::recursive_directory_iterator{sandbox})
std::cout << dir_entry << '\n';
// delete the sandbox dir and all contents within it, including subdirs
// 遞歸刪除該目錄所有內(nèi)容 相當(dāng)于 rm -rf sandbox
std::filesystem::remove_all(sandbox);
}
output:
directory_iterator: "sandbox/dir1" "sandbox/file1.txt" "sandbox/file2.txt" recursive_directory_iterator: "sandbox/dir1" "sandbox/dir1/dir2" "sandbox/file1.txt" "sandbox/file2.txt"
四、文件類型判斷
在filesystem庫中使用枚舉類型file_type對(duì)文件類型進(jìn)行定義
| 常量 | 含義 |
|---|---|
| none | 文件狀態(tài)尚未求值,或求值時(shí)發(fā)生錯(cuò)誤 |
| not_foud | 找不到該文件 |
| regular | 常規(guī)文件(二進(jìn)制、文本等) |
| directory | 目錄 |
| symlink | 符號(hào)鏈接 |
| block | 塊(設(shè)備) |
| character | 塊(設(shè)備) |
| fifo | 管道類型文件 |
| socket | socket |
| unknown | 文件存在但類型不確定 |
demo:
#include <cstdio>
#include <cstring>
#include <filesystem>
#include <fstream>
#include <iostream>
#include <sys/socket.h>
#include <sys/stat.h>
#include <sys/un.h>
#include <unistd.h>
namespace fs = std::filesystem;
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';
}
int main()
{
// create files of different kinds
fs::create_directory("sandbox");
fs::create_directory("sandbox/dir");
std::ofstream{"sandbox/file"}; // create regular file
fs::create_symlink("file", "sandbox/symlink");
mkfifo("sandbox/pipe", 0644);
sockaddr_un addr;
addr.sun_family = AF_UNIX;
std::strcpy(addr.sun_path, "sandbox/sock");
int fd = socket(PF_UNIX, SOCK_STREAM, 0);
bind(fd, reinterpret_cast<sockaddr*>(&addr), sizeof addr);
// demo different status accessors
for (auto it{fs::directory_iterator("sandbox")}; it != fs::directory_iterator(); ++it)
demo_status(*it, it->symlink_status()); // use cached status from directory entry
demo_status("/dev/null", fs::status("/dev/null")); // direct calls to status
demo_status("/dev/sda", fs::status("/dev/sda"));
demo_status("sandbox/no", fs::status("/sandbox/no"));
// cleanup (prefer std::unique_ptr-based custom deleters)
close(fd);
fs::remove_all("sandbox");
}
到此這篇關(guān)于C++20中filesystem庫的使用的文章就介紹到這了,更多相關(guān)C++20 filesystem庫內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
如何用C++實(shí)現(xiàn)雙向循環(huán)鏈表
本篇文章是對(duì)用C++實(shí)現(xiàn)雙向循環(huán)鏈表的方法進(jìn)行了詳細(xì)的分析介紹,需要的朋友參考下2013-05-05
C++實(shí)現(xiàn)高校人員信息管理系統(tǒng)
這篇文章主要為大家詳細(xì)介紹了C++實(shí)現(xiàn)高校人員信息管理系統(tǒng)項(xiàng),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-06-06
Easyx實(shí)現(xiàn)窗口自動(dòng)碰撞的小球
這篇文章主要為大家詳細(xì)介紹了Easyx實(shí)現(xiàn)窗口自動(dòng)碰撞的小球,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-01-01

