C++17?Filesystem?實(shí)用教程
C++17 標(biāo)準(zhǔn)帶來(lái)了 std::filesystem
庫(kù), 提供了強(qiáng)大的工具來(lái)處理文件路徑, 目錄以及其他與文件系統(tǒng)相關(guān)的操作. 這篇文章適合 C++ 初學(xué)者以及希望掌握 C++17 新特性的開發(fā)者, 旨在幫助他們高效地完成文件系統(tǒng)相關(guān)任務(wù).
什么是 std::filesystem?
std::filesystem
是 C++ 標(biāo)準(zhǔn)庫(kù)的一部分, 位于 std::filesystem
名稱空間中. 它提供了一個(gè)平臺(tái) 獨(dú)立的方式來(lái)與文件系統(tǒng)交互, 支持目錄導(dǎo)航, 查詢文件屬性和實(shí)現(xiàn)文件操作等功能.
為什么使用 std::filesystem?
在 C++17 之前, 開發(fā)者依賴于平臺(tái)特定的 API 或第三方庫(kù)進(jìn)行文件操作, 導(dǎo)致可移植性的挑戰(zhàn). 使用 std::filesystem
, 您可以獲得:
- 跨平臺(tái)支持: 為 Windows, Linux 和 macOS 提供統(tǒng)一的 API.
- 便據(jù)性: 提供相關(guān)文件操作的直觀函數(shù).
- 性能: 接口實(shí)現(xiàn)根據(jù)平臺(tái)做了優(yōu)化處理.
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; }
為了保持代碼簡(jiǎn)潔, 后續(xù)代碼中將不再包含頭文件和main
函數(shù)體, 讀者可以從文末的源碼鏈接獲取完整源代碼.
2. 創(chuàng)建和刪除目錄
fs::path dirPath = "new_directory"; fs::create_directory(dirPath); // 創(chuàng)建單個(gè)目錄 fs::remove(dirPath); // 刪除目錄
3. 遍歷目錄
fs::path dirPath = "."; // 當(dāng)前目錄 for (const auto& entry : fs::recursive_directory_iterator(dirPath)) { std::cout << entry.path() << std::endl; }
此示例會(huì)遞歸列出當(dāng)前目錄及其所有子目錄中的文件和文件夾.
4. 查詢文件屬性
fs::path filePath = "example.txt"; if (fs::exists(filePath)) { std::cout << "文件大小: " << fs::file_size(filePath) << " 字節(jié)\n"; std::cout << "是否為正解文件: " << fs::is_regular_file(filePath) << "\n"; std::cout << "文件最后修改時(shí)間: " << fs::last_write_time(filePath).time_since_epoch().count() << "\n"; }
5. 復(fù)制和重命名文件
fs::copy("source.txt", "destination.txt", fs::copy_options::overwrite_existing); // 復(fù)制文件 fs::rename("old_name.txt", "new_name.txt"); // 重命名文件
6. 處理符號(hào)鏈接
fs::path symlinkPath = "symbolic_link"; fs::path targetPath = "target_file"; fs::create_symlink(targetPath, symlinkPath); // 創(chuàng)建符號(hào)鏈接 if (fs::is_symlink(symlinkPath)) { std::cout << symlinkPath << " 是符號(hào)鏈接, 指向 " << fs::read_symlink(symlinkPath) << std::endl; }
路徑相關(guān)操作
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 << "擴(kuò)展名: " << filepath.extension() << std::endl; std::cout << "父路徑: " << filepath.parent_path() << std::endl;
輸出
文件名: "report.pdf"
主文件名: "report"
擴(kuò)展名: ".pdf"
父路徑: "/home/user/documents"
7.3 相對(duì)路徑計(jì)算
fs::path p1 = "/home/user/documents"; fs::path p2 = "/home/user/pictures"; fs::path rel = fs::relative(p2, p1); // 計(jì)算從 p1 到 p2 的相對(duì)路徑 std::cout << "相對(duì)路徑: " << rel << std::endl; // ../pictures
輸出
相對(duì)路徑: "../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 詞法規(guī)范化路徑
fs::path messy = "home/user/../user/./documents/report.pdf"; std::cout << "規(guī)范化路徑: " << messy.lexically_normal() << std::endl;
輸出
規(guī)范化路徑: "home/user/documents/report.pdf"
7.6 路徑比較
// 使用 std::filesystem::equivalent 檢查兩個(gè)路徑是否指向同一文件 fs::path linkPath = "link_to_report.pdf"; // 假設(shè)這是一個(gè)指向 report.pdf 的符號(hào)鏈接 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 << "文件系統(tǒng)錯(cuò)誤: " << 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 << "是否為絕對(duì)路徑: " << checkPath.is_absolute() << std::endl; std::cout << "是否有擴(kuò)展名: " << checkPath.has_extension() << std::endl; std::cout << "是否有文件名: " << checkPath.has_filename() << std::endl; std::cout << "是否有父路徑: " << checkPath.has_parent_path() << std::endl;
輸出
是否為絕對(duì)路徑: 1
是否有擴(kuò)展名: 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 << "替換擴(kuò)展名后: " << modPath << std::endl;
輸出
替換文件名后: "/home/user/documents/newreport.doc"
替換擴(kuò)展名后: "/home/user/documents/newreport.txt"
注意事項(xiàng):
- 路徑操作是純字符串操作, 不涉及實(shí)際文件系統(tǒng)
- 這些操作在 Windows 和 Unix 系統(tǒng)上都能正常工作
- 使用
/
操作符組合路徑比直接字符串拼接更安全 lexically_normal()
可以清理路徑中的.
和..
最佳實(shí)踐
錯(cuò)誤處理:
- 使用異常處理來(lái)捕獲和管理錯(cuò)誤情況. 許多
std::filesystem
函數(shù)會(huì)拋出std::filesystem::filesystem_error
, 例如在沒(méi)有刪除權(quán)限時(shí).
- 使用異常處理來(lái)捕獲和管理錯(cuò)誤情況. 許多
路徑類型:
- 使用
fs::absolute
將相對(duì)路徑轉(zhuǎn)換為絕對(duì)路徑, 以確保路徑的完整性和清晰性.
- 使用
性能優(yōu)化:
- 對(duì)于網(wǎng)絡(luò)磁盤或涉及大量文件的操作, 盡量減少 I/O 操作以提高性能.
跨平臺(tái)注意事項(xiàng):
- 路徑格式: 雖然
std::filesystem
自動(dòng)處理不同平臺(tái)的路徑分隔符差異(Windows 使用\
, 其他平臺(tái)使用/
), 但建議始終使用fs::path
進(jìn)行路徑操作. - 文件權(quán)限: 不同平臺(tái)的文件權(quán)限管理可能不一致, 尤其是
fs::permissions
.
- 路徑格式: 雖然
路徑組合:
- 使用
/
操作符組合路徑比直接字符串拼接更安全.
- 使用
路徑規(guī)范化:
- 使用
lexically_normal()
清理路徑中的.
和..
, 以獲得更簡(jiǎn)潔的路徑表示.
- 使用
限制性
- 調(diào)用鏈接文件: 包含鏈接文件的操作在不同平臺(tái)上有不同表現(xiàn).
- 性能: 盡管高效, 部分文件系統(tǒng)操作在網(wǎng)絡(luò)磁盤上仍會(huì)突出慢.
結(jié)論
std::filesystem
庫(kù)是 C++ 重要的增加, 使文件和目錄操作更加簡(jiǎn)單和可移植. 無(wú)論您是在寫一個(gè)簡(jiǎn)單腳本, 還是構(gòu)建復(fù)雜應(yīng)用, 熟練該庫(kù)都是值得一試的.
開始探索 std::filesystem
, 你將發(fā)現(xiàn)它是你 C++ 程序裝備中一個(gè)珍貴的工具!
到此這篇關(guān)于C++17 Filesystem 實(shí)用教程的文章就介紹到這了,更多相關(guān)C++17 Filesystem內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
C++使用LibCurl實(shí)現(xiàn)Web隱藏目錄掃描功能
LibCurl是一個(gè)開源的免費(fèi)的多協(xié)議數(shù)據(jù)傳輸開源庫(kù),該框架具備跨平臺(tái)性,開源免費(fèi),并提供了包括HTTP、FTP、SMTP、POP3等協(xié)議的功能,本文將給大家介紹C++使用LibCurl實(shí)現(xiàn)Web隱藏目錄掃描功能2023-11-11