Dateisystemnavigation

Der <filesystem> Header implementiert die technische C++-Dateisystemspezifikation ISO/IEC TS 18822:2015 (Endgültiger Entwurf: ISO/IEC JTC 1/SC 22/WG 21 N4100) und verfügt über Typen und Funktionen, mit denen Sie plattformunabhängigen Code für die Navigation im Dateisystem schreiben können. Da es plattformübergreifend ist, enthält es APIs, die für Windows-Systeme nicht relevant sind. Gibt beispielsweise is_fifo(const path&) immer unter Windows zurück false .

Überblick

Verwenden Sie die <filesystem> APIs für die folgenden Aufgaben:

  • Durchlaufen von Dateien und Verzeichnissen unter einem angegebenen Pfad

  • Abrufen von Informationen zu Dateien, einschließlich Erstellungszeitpunkt, Größe, Erweiterung und Stammverzeichnis

  • Erstellen, Zerlegen und Vergleichen von Pfaden

  • Erstellen, Kopieren und Löschen von Verzeichnissen

  • Kopieren und Löschen von Dateien

Weitere Informationen zu Datei-E/A mit der Standardbibliothek finden Sie unter iostream-Programmierung.

Paths

Erstellen und Zerlegen von Pfaden

In Windows (ab XP) werden Pfade systemintern in Unicode gespeichert. Die path Klasse führt automatisch alle erforderlichen Zeichenfolgenkonvertierungen durch. Es akzeptiert Argumente von breiten und schmalen Zeichenarrays und beide std::string Typen std::wstring , die als UTF8 oder UTF16 formatiert sind. Mit der path -Klasse werden Pfadtrennzeichen automatisch normalisiert. Sie können einen einzelnen Schrägstrich als Verzeichnistrennzeichen in Konstruktorargumenten verwenden. Mit diesem Trennzeichen können Sie dieselben Zeichenfolgen verwenden, um Pfade in Windows- und UNIX-Umgebungen zu speichern:

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.

Zum Verketten zweier Pfade können Sie überladene / - und /= -Operatoren verwenden, die analog zu den + - und += -Operatoren in std::string und std::wstringsind. Das path Objekt stellt die Trennzeichen bequem zur Verfügung, wenn sie nicht.

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

Überprüfen von Pfaden

Die Pfadklasse verfügt über mehrere Methoden, die Informationen zu verschiedenen Teilen des Pfads selbst zurückgeben. Diese Informationen unterscheiden sich von den Informationen über die Dateisystementität, auf die sie sich möglicherweise beziehen kann. Sie können den Stamm, relativen Pfad, Dateinamen, die Dateierweiterung usw. abrufen. Sie können Pfadobjekte durchlaufen, um alle Ordner in der Hierarchie zu überprüfen. Das folgende Beispiel zeigt, wie Sie ein Pfadobjekt durchlaufen. Und wie Sie Informationen zu ihren Teilen abrufen.

// 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);
}

Durch den Code wird die folgende Ausgabe generiert:

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

Vergleichen von Pfaden

Die path -Klasse überlädt die gleichen Vergleichsoperatoren wie std::string und std::wstring. Wenn Sie zwei Pfade vergleichen, erstellen Sie einen Zeichenfolgenvergleich, nachdem die Trennzeichen normalisiert wurden. Wenn ein nachgestellter Schrägstrich (oder umgekehrter Schrägstrich) fehlt, wird er nicht hinzugefügt und wirkt sich auf den Vergleich aus. Im folgenden Beispiel wird der Vergleich von Pfadwerten veranschaulicht:

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

Um diesen Code auszuführen, fügen Sie ihn in das vollständige Beispiel oben vor main ein, und heben Sie in main die Auskommentierung der Zeile auf, die ihn aufruft.

Konvertieren zwischen Pfad- und Zeichenfolgentypen

Ein path -Objekt ist implizit in std::wstring oder std::stringkonvertibel. Dies bedeutet, dass Sie einen Pfad zu Funktionen übergeben können, z wofstream::open. B. wie in diesem Beispiel gezeigt:

// 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

Durchlaufen von Verzeichnissen und Dateien

Der <filesystem> Header stellt den directory_iterator Typ zum Durchlaufen einzelner Verzeichnisse bereit, und die recursive_directory_iterator Klasse, um rekursiv über ein Verzeichnis und seine Unterverzeichnisse zu durchlaufen. Wenn Sie einen Iterator erstellt haben, indem Sie ihm ein path -Objekt übergeben haben, verweist der Iterator auf den ersten „directory_entry“ im Pfad. Erstellen Sie den End-Iterator, indem Sie den Standardkonstruktor aufrufen.

Beim Durchlaufen eines Verzeichnisses gibt es mehrere Arten von Elementen, die Sie möglicherweise entdecken. Zu diesen Elementen gehören Verzeichnisse, Dateien, symbolische Verknüpfungen, Socketdateien und andere. Die directory_iterator Elemente werden als directory_entry Objekte zurückgegeben.