跳至內容

C++/STL/filesystem

維基教科書,自由的教學讀本
< C++

std::filesystem文件系統庫提供了文件系統、路徑、常規文件、目錄等等相關組件進行操作的相關功能。

幾個基本類:

  • path: 表示路徑
  • directory_entry:目錄條目
  • space_info:關於文件系統上空閒及可用空間的信息
  • directory_iterator:對目錄做迭代訪問
  • recursive_directory_iterator:對目錄几子目錄迭代訪問

path類

[編輯]
#include <iostream>
#include <filesystem>
#include <string>
 
namespace fs = std::filesystem;
 
void path_use()
{
    fs::path currentPath = fs::current_path();
    //获取makefile路径  append operator/ 添加元素到带目录分隔符的路径
    fs::path makefilePath = currentPath / "ConsoleApplication1.vcxproj";
    std::cout << "Project file path      = " << makefilePath.string() << std::endl;
    //分解操作
    //root_name 返回路径的根名
    std::cout << "root_name          = " << currentPath.root_name() << std::endl;
    //root_directory 返回路径的根目录
    std::cout << "root_directory     = " << currentPath.root_directory() << std::endl;
    //root_path 返回路径的根路径
    std::cout << "root_path          = " << currentPath.root_path() << std::endl;
    //relative_path 返回相对根路径的路径
    std::cout << "relative_path      = " << currentPath.relative_path() << std::endl;
    //parent_path 返回亲路径的路径
    std::cout << "parent_path        = " << currentPath.parent_path() << std::endl;
    //filename 返回文件名路径组分
    std::cout << "filename           = " << currentPath.filename() << std::endl;
    //stem 返回主干路径组分
    std::cout << "stem               = " << currentPath.stem() << std::endl;
    //extension 返回文件扩展名路径组分
    std::cout << "extension          = " << currentPath.extension() << std::endl;
    std::cout << "extension          = " << makefilePath.extension() << std::endl;
 
    //查询操作
    //empty 检查路径是否为空
    std::cout << "empty              = " << currentPath.empty() << std::endl;
    //检查对应路径元素是否非空
    std::cout << "has_root_path      = " << currentPath.has_root_path() << std::endl;
    std::cout << "has_root_name      = " << currentPath.has_root_name() << std::endl;
    std::cout << "has_root_directory = " << currentPath.has_root_directory() << std::endl;
    std::cout << "has_relative_path  = " << currentPath.has_relative_path() << std::endl;
    std::cout << "has_parent_path    = " << currentPath.has_parent_path() << std::endl;
    std::cout << "has_filename       = " << currentPath.has_filename() << std::endl;
    std::cout << "has_stem           = " << currentPath.has_stem() << std::endl;
    std::cout << "has_extension      = " << currentPath.has_extension() << std::endl;
 
    //检查 root_path() 是否唯一标识文件系统位置
    std::cout << "is_absolute        = " << currentPath.is_absolute() << std::endl;
    std::cout << "is_relative        = " << currentPath.is_relative() << std::endl;
}
 
int main()
{
    path_use();
    std::cout << std::endl;
    return 0;
}
/*输出为:
Project file path      = D:\MyPrograms\ConsoleApplication1\ConsoleApplication1\ConsoleApplication1.vcxproj
root_name          = "D:"
root_directory     = "\\"
root_path          = "D:\\"
relative_path      = "MyPrograms\\ConsoleApplication1\\ConsoleApplication1"
parent_path        = "D:\\MyPrograms\\ConsoleApplication1"
filename           = "ConsoleApplication1"
stem               = "ConsoleApplication1"
extension          = ""
extension          = ".vcxproj"
empty              = 0
has_root_path      = 1
has_root_name      = 1
has_root_directory = 1
has_relative_path  = 1
has_parent_path    = 1
has_filename       = 1
has_stem           = 1
has_extension      = 0
is_absolute        = 1
is_relative        = 0
*/

directory_entry

[編輯]
void directory_entry_use()
{
    //path operator const path& 返回该目录项代表的路径
    fs::path currentPath = fs::current_path();
    //获取makefile路径  append operator/ 添加元素到带目录分隔符的路径
    fs::path makefilePath = currentPath / "ConsoleApplication1.vcxproj";
    std::cout << "Project file path      = " << makefilePath.string() << std::endl;
    fs::directory_entry dirEntry(currentPath);
    //exists 检查 directory_entry 是否代表既存文件系统对象
    std::cout << "exists             = " << dirEntry.exists() << std::endl;
    //is_block_file 检查 directory_entry 是否代表阻塞设备
    std::cout << "is_block_file      = " << dirEntry.is_block_file() << std::endl;
    //is_character_file 检查 directory_entry 是否代表字符设备
    std::cout << "is_character_file  = " << dirEntry.is_character_file() << std::endl;
    //is_directory 检查 directory_entry 是否代表目录
    std::cout << "is_directory       = " << dirEntry.is_directory() << std::endl;
    //is_fifo 检查 directory_entry 是否代表具名管道
    std::cout << "is_fifo            = " << dirEntry.is_fifo() << std::endl;
    //is_other 检查 directory_entry 是否代表其他文件
    std::cout << "is_other           = " << dirEntry.is_other() << std::endl;
    //is_regular_file 检查 directory_entry 是否代表常规文件
    std::cout << "is_regular_file    = " << dirEntry.is_regular_file() << std::endl;
    //is_socket 检查 directory_entry 是否代表具名 IPC 接头
    std::cout << "is_socket          = " << dirEntry.is_socket() << std::endl;
    //is_symlink 检查 directory_entry 是否代表符号链接
    std::cout << "is_symlink         = " << dirEntry.is_symlink() << std::endl;
    //file_size 返回 directory_entry 所指代的文件大小
    std::cout << "file_size          = " << dirEntry.file_size() << std::endl;
    //hard_link_count 返回引用到该  directory_entry 所表示的文件的硬链接数
    std::cout << "hard_link_count    = " << dirEntry.hard_link_count() << std::endl;
 
}
 
int main()
{
    directory_entry_use();
    return 0;
}
/*输出为:
Project file path      = D:\MyPrograms\ConsoleApplication1\ConsoleApplication1\ConsoleApplication1.vcxproj
exists             = 1
is_block_file      = 0
is_character_file  = 0
is_directory       = 1
is_fifo            = 0
is_other           = 0
is_regular_file    = 0
is_socket          = 0
is_symlink         = 0
file_size          = 4096
hard_link_count    = 1
*/

space_info

[編輯]
void space_info_use()
{
    //capacity文件系统的总大小,以字节计
    //free文件系统的空闲空间,以字节计
    //available非特权进程可用的空闲空间(可以小于或等于 free )
    fs::path currentPath = fs::current_path();
    std::cout << "Current path is " << fs::current_path() << std::endl;
    fs::path parentPath = currentPath.parent_path();
    std::cout << "Parent  path is " << parentPath.string() << std::endl;
    fs::space_info devi = fs::space(currentPath);
    fs::space_info tmpi = fs::space(parentPath);
 
    std::cout << ".                 Capacity       Free        Available\n"
              << "current path:   " << devi.capacity << "   "
              << devi.free << "   " << devi.available  << '\n'
              << "parent  path:   " << tmpi.capacity << "   "
              << tmpi.free << "   " << tmpi.available  << '\n';
 
}
 
int main()
{
    space_info_use();
    return 0;
}
/*输出为:
Current path is "D:\\MyPrograms\\ConsoleApplication1\\ConsoleApplication1"
Parent  path is D:\MyPrograms\ConsoleApplication1
.                 Capacity       Free        Available
current path:   668955832320   442984341504   442984341504
parent  path:   668955832320   442984341504   442984341504
*/

目錄迭代

[編輯]
#include <fstream>
#include <iostream>
#include <filesystem>
#include <algorithm>
 
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"};
 
    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 << '\n';
    }
 
    std::cout << "\ndirectory_iterator as a range:\n";
    // directory_iterator behaves as a range in other ways, too
    std::ranges::for_each( std::filesystem::directory_iterator{sandbox},
                           [](const auto& dir_entry) {
                             std::cout << dir_entry << '\n';
                           } );
 
    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
    std::filesystem::remove_all(sandbox);
}
/*
Possible output:

directory_iterator:
"sandbox/file2.txt"
"sandbox/file1.txt"
"sandbox/dir1"
 
directory_iterator as a range:
"sandbox/file2.txt"
"sandbox/file1.txt"
"sandbox/dir1"
 
recursive_directory_iterator:
"sandbox/file2.txt"
"sandbox/file1.txt"
"sandbox/dir1"
"sandbox/dir1/dir2"
*/