Partager via


Navigation dans le système de fichiers

L’en-tête <filesystem> implémente la spécification technique du système de fichiers C++ ISO/IEC TS 18822:2015 (brouillon final : ISO/IEC JTC 1/SC 22/WG 21 N4100) et dispose de types et de fonctions qui vous permettent d’écrire du code indépendant de la plateforme pour naviguer dans le système de fichiers. Comme il s’agit d’une plateforme multiplateforme, il contient des API qui ne sont pas pertinentes pour les systèmes Windows. Par exemple, is_fifo(const path&) retourne false toujours sur Windows.

Vue d’ensemble

Utilisez les <filesystem> API pour les tâches suivantes :

  • effectuer une itération des fichiers et répertoires sous un chemin d'accès spécifié ;

  • obtenir des informations sur les fichiers (date de création, taille, extension, répertoire racine, etc.) ;

  • composer, décomposer et comparer des chemins d'accès ;

  • créer, copier et supprimer des répertoires

  • copier et supprimer des fichiers.

Pour plus d’informations sur les E/S de fichiers avec la bibliothèque standard, consultez iostream, programmation.

Chemins

Construction et composition de chemins d'accès

Dans Windows (depuis XP), les chemins d'accès sont stockés en mode natif au format Unicode. La path classe effectue automatiquement toutes les conversions de chaînes nécessaires. Il accepte les arguments des tableaux de caractères larges et étroits, ainsi std::wstring que les types std::string mis en forme comme UTF8 ou UTF16. La classe path normalise aussi automatiquement les séparateurs des chemins. Vous pouvez utiliser une seule barre oblique comme séparateur de répertoires dans les arguments de constructeur. Ce séparateur vous permet d’utiliser les mêmes chaînes pour stocker les chemins d’accès dans les environnements Windows et UNIX :

path pathToDisplay(L"/FileSystemTest/SubDir3");     // OK!
path pathToDisplay2(L"\\FileSystemTest\\SubDir3");  // Still OK as always
path pathToDisplay3(LR"(\FileSystemTest\SubDir3)"); // Raw string literals are OK, too.

Pour concaténer deux chemins, utilisez les opérateurs / et /= surchargés, qui sont similaires aux opérateurs + et += sur std::string et std::wstring. L’objet path fournit facilement les séparateurs si ce n’est pas le cas.

path myRoot("C:/FileSystemTest");  // no trailing separator, no problem!
myRoot /= path("SubDirRoot");      // C:/FileSystemTest/SubDirRoot

Examen des chemins d'accès

La classe path a plusieurs méthodes qui retournent des informations sur différentes parties du chemin lui-même. Ces informations sont distinctes des informations relatives à l’entité du système de fichiers auquel il peut faire référence. Vous pouvez ainsi obtenir la racine, le chemin d'accès relatif, le nom et l'extension de fichier, etc. Vous pouvez itérer un objet path pour examiner tous les répertoires de l'arborescence. L’exemple suivant montre comment itérer sur un objet path. Et comment récupérer des informations sur ses parties.

// filesystem_path_example.cpp
// compile by using: /EHsc /W4 /permissive- /std:c++17 (or later)
#include <string>
#include <iostream>
#include <sstream>
#include <filesystem>

using namespace std;
using namespace std::filesystem;

wstring DisplayPathInfo()
{
    // This path may or may not refer to an existing file. We are
    // examining this path string, not file system objects.
    path pathToDisplay(L"C:/FileSystemTest/SubDir3/SubDirLevel2/File2.txt ");

    wostringstream wos;
    int i = 0;
    wos << L"Displaying path info for: " << pathToDisplay << endl;
    for (path::iterator itr = pathToDisplay.begin(); itr != pathToDisplay.end(); ++itr)
    {
        wos << L"path part: " << i++ << L" = " << *itr << endl;
    }

    wos << L"root_name() = " << pathToDisplay.root_name() << endl
        << L"root_path() = " << pathToDisplay.root_path() << endl
        << L"relative_path() = " << pathToDisplay.relative_path() << endl
        << L"parent_path() = " << pathToDisplay.parent_path() << endl
        << L"filename() = " << pathToDisplay.filename() << endl
        << L"stem() = " << pathToDisplay.stem() << endl
        << L"extension() = " << pathToDisplay.extension() << endl;

    return wos.str();
}

int main()
{
    wcout << DisplayPathInfo() << endl;
    // wcout << ComparePaths() << endl; // see following example
    wcout << endl << L"Press Enter to exit" << endl;
    wstring input;
    getline(wcin, input);
}

Le code génère cette sortie :

Displaying path info for: C:\FileSystemTest\SubDir3\SubDirLevel2\File2.txt
path part: 0 = C:
path part: 1 = \
path part: 2 = FileSystemTest
path part: 3 = SubDir3
path part: 4 = SubDirLevel2
path part: 5 = File2.txt
root_name() = C:
root_path() = C:\
relative_path() = FileSystemTest\SubDir3\SubDirLevel2\File2.txt
parent_path() = C:\FileSystemTest\SubDir3\SubDirLevel2
filename() = File2.txt
stem() = File2
extension() = .txt

Comparaison des chemins d'accès

La classe path surcharge les mêmes opérateurs de comparaison que std::string et std::wstring. Lorsque vous comparez deux chemins, vous effectuez une comparaison de chaînes après la normalisation des séparateurs. Si une barre oblique de fin (ou barre oblique inverse) est manquante, elle n’est pas ajoutée et affecte la comparaison. L'exemple suivant montre comment les valeurs de chemin d'accès sont comparées :

wstring ComparePaths()
{
    path p0(L"C:/Documents");                 // no trailing separator
    path p1(L"C:/Documents/");                // p0 < p1
    path p2(L"C:/Documents/2013/");           // p1 < p2
    path p3(L"C:/Documents/2013/Reports/");   // p2 < p3
    path p4(L"C:/Documents/2014/");           // p3 < p4
    path p5(L"D:/Documents/2013/Reports/");   // p4 < p5

    wostringstream wos;
    wos << boolalpha <<
        p0.wstring() << L" < " << p1.wstring() << L": " << (p0 < p1) << endl <<
        p1.wstring() << L" < " << p2.wstring() << L": " << (p1 < p2) << endl <<
        p2.wstring() << L" < " << p3.wstring() << L": " << (p2 < p3) << endl <<
        p3.wstring() << L" < " << p4.wstring() << L": " << (p3 < p4) << endl <<
        p4.wstring() << L" < " << p5.wstring() << L": " << (p4 < p5) << endl;
    return wos.str();
}
C:\Documents < C:\Documents\: true
C:\Documents\ < C:\Documents\2013\: true
C:\Documents\2013\ < C:\Documents\2013\Reports\: true
C:\Documents\2013\Reports\ < C:\Documents\2014\: true
C:\Documents\2014\ < D:\Documents\2013\Reports\: true

Pour exécuter ce code, collez-le dans l’exemple complet ci-dessus avant main et supprimez les commentaires de la ligne qui l’appelle dans la fonction main.

Conversion entre les types chemin d'accès et chaîne

Un objet path est implicitement convertible en std::wstring ou en std::string. Cela signifie que vous pouvez passer un chemin d’accès à des fonctions telles que wofstream::open, comme illustré dans cet exemple :

// filesystem_path_conversion.cpp
// compile by using: /EHsc /W4 /permissive- /std:c++17 (or later)
#include <string>
#include <iostream>
#include <fstream>
#include <filesystem>

using namespace std;
using namespace std::filesystem;

int main()
{
    const wchar_t* p{ L"C:/Users/Public/Documents" };
    path filePath(p);

    filePath /= L"NewFile.txt";

    // Open, write to, and close the file.
    wofstream writeFile(filePath, ios::out);  // implicit conversion
    writeFile << L"Lorem ipsum\nDolor sit amet";
    writeFile.close();

    // Open, read, and close the file.
    wifstream readFile;
    wstring line;
    readFile.open(filePath);  // implicit conversions
    wcout << L"File " << filePath << L" contains:" << endl;
    while (readFile.good())
    {
        getline(readFile, line);
        wcout << line << endl;
    }
    readFile.close();

    wcout << endl << L"Press Enter to exit" << endl;
    wstring input;
    getline(wcin, input);
}
File C:\Users\Public\Documents\NewFile.txt contains:
Lorem ipsum
Dolor sit amet

Press Enter to exit

Itération de répertoires et de fichiers

L’en-tête <filesystem> fournit le directory_iterator type pour itérer sur des répertoires uniques, et la recursive_directory_iterator classe pour itérer de manière récursive sur un répertoire et ses sous-répertoires. Après avoir construit un itérateur en lui passant un objet path , l’itérateur pointe vers le premier objet directory_entry dans le chemin. Créez l'itérateur de fin en appelant le constructeur par défaut.

Lors de l’itération dans un répertoire, il existe plusieurs types d’éléments que vous pouvez découvrir. Ces éléments incluent des répertoires, des fichiers, des liens symboliques, des fichiers de socket et d’autres. Renvoie directory_iterator ses éléments en tant qu’objets directory_entry .