Nawigacja w systemie plików

Nagłówek implementuje specyfikację techniczną systemu plików <filesystem> C++ ISO/IEC TS 18822:2015 (ostateczna wersja robocza: <filesystem>) oraz zawiera typy i funkcje, które umożliwiają pisanie kodu niezależnego od platformy do nawigowania po systemie plików. Ponieważ jest ona międzyplatformowa, zawiera interfejsy API, które nie są istotne dla Windows systemów. Na przykład zawsze is_fifo(const path&) zwraca false wartość Windows.

Omówienie

Użyj <filesystem> interfejsów API do wykonywania następujących zadań:

  • iteruj pliki i katalogi w określonej ścieżce

  • uzyskiwanie informacji o plikach, w tym o czasie utworzenia, rozmiarze, rozszerzeniu i katalogu głównym

  • redagowanie, dekomponowanie i porównywanie ścieżek

  • tworzenie, kopiowanie i usuwanie katalogów

  • kopiowanie i usuwanie plików

Aby uzyskać więcej informacji na temat we/wy plików przy użyciu biblioteki standardowej, zobacz iostream Programming ( Programowanie iostream).

Ścieżki

Konstruowanie i tworzenie ścieżek

Ścieżki w Windows (od XP) są przechowywane natywnie w standardzie Unicode. Klasa path automatycznie robi wszystkie niezbędne konwersje ciągów. Akceptuje argumenty zarówno szerokiej, jak i wąskiej tablicy znaków oraz typów i sformatowanych jako std::stringstd::wstring UTF8 lub UTF16. Klasa path automatycznie normalizuje również separatory ścieżek. Można użyć pojedynczego ukośnika jako separatora katalogu w argumentach konstruktora. Ten separator umożliwia używanie tych samych ciągów do przechowywania ścieżek w Windows i system UNIX środowisku:

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.

Aby zjednocić dwie ścieżki, można użyć przeciążonych operatorów i , które są analogiczne do operatorów //= i w i ++=std::stringstd::wstring . Jeśli nie, obiekt będzie wygodnie path dostarczać separatory.

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

Badanie ścieżek

Klasa path ma kilka metod, które zwracają informacje o różnych częściach samej ścieżki. Te informacje różnią się od informacji o jednostce systemu plików, do których może się odnosić. Możesz uzyskać katalog główny, ścieżkę względną, nazwę pliku, rozszerzenie pliku i inne. Możesz iterować po obiekcie ścieżki, aby zbadać wszystkie foldery w hierarchii. W poniższym przykładzie pokazano, jak iterować po obiekcie ścieżki. Oraz jak pobierać informacje o jego częściach.

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

Kod generuje te dane wyjściowe:

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

Porównywanie ścieżek

Klasa path przeciąża te same operatory porównania co std::string i std::wstring . Podczas porównywania dwóch ścieżek należy wykonać porównanie ciągów po znormalizowaniu separatorów. Jeśli brakuje końcowego ukośnika (lub ukośnika odwrotnego), nie zostanie on dodany i będzie to miało wpływ na porównanie. W poniższym przykładzie pokazano sposób porównywania wartości ścieżek:

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

Aby uruchomić ten kod, wklej go do pełnego przykładu powyżej przed i odkomentuj wiersz, który main wywołuje go w trybie main.

Konwertowanie między ścieżkami i typami ciągów

Obiekt path jest niejawnie konwertowany na std::wstring obiekt lub std::string . Oznacza to, że można przekazać ścieżkę do funkcji, takich jak wofstream::open , jak pokazano w tym przykładzie:

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

Iterowanie katalogów i plików

Nagłówek zawiera typ do iterować po pojedynczych katalogach, a klasa do cyklicznego iterować po katalogu i <filesystem>directory_iterator jego recursive_directory_iterator podkatalogach. Po skonstruowaniu iteratora przez przekazanie do niego obiektu iterator wskazuje pierwszy directory_entry path w ścieżce. Utwórz iterator końcowy, wywołując konstruktor domyślny.

Podczas iterowania po katalogu istnieje kilka rodzajów elementów, które można odnaleźć. Te elementy obejmują katalogi, pliki, linki symboliczne, pliki gniazd i inne. Element directory_iterator zwraca jego elementy jako directory_entry obiekty.