Die Klasse boost::filesystem::path
ist die zentrale Klasse in Boost.Filesystem. Sie repräsentiert Pfadangaben und bietet zahlreiche Methoden an, um Pfadangaben zu verarbeiten.
Die Headerdatei, die Sie zur Verarbeitung von Pfadangaben einbinden müssen, ist boost/filesystem.hpp
. Alle von Boost.Filesystem angebotenen Klassen und Funktionen befinden sich im Namensraum boost::filesystem
.
Sie können Pfadangaben bilden, indem Sie die Klasse boost::filesystem::path
wie im Beispiel 35.1 mit einem entsprechenden String initialisieren.
boost::filesystem::path
in Aktion#include <boost/filesystem.hpp>
using namespace boost::filesystem;
int main()
{
path p1{"C:\\"};
path p2{"C:\\Windows"};
path p3{L"C:\\Boost C++ \u5E93"};
}
Sie können boost::filesystem::path
mit Wide-Strings initialisieren. Boost.Filesystem interpretiert Wide-Strings im Unicode-Format, so dass Pfadangaben erstellt werden können, die exotische Zeichen enthalten. Dies ist ein entscheidender Unterschied zum Vorgänger Boost.Filesystem 2, der mehrere Klassen wie boost::filesystem::path
und boost::filesystem::wpath
für unterschiedliche String-Typen anbot.
Beachten Sie, dass Boost.Filesystem keine Pfadangaben vom Typ std::u16string
oder std::u32string
unterstützt. Ihr Compiler bricht mit einer Fehlermeldung ab, wenn Sie versuchen, eine Pfadangabe von einem dieser String-Typen an den Konstruktor von boost::filesystem::path
zu übergeben.
Die Konstruktoren von boost::filesystem::path
überprüfen nicht, ob eine Pfadangabe Sinn ergibt und ob eine entsprechende Datei oder ein Verzeichnis existiert. Selbst mit offensichtlich unsinnigen Pfadangaben kann boost::filesystem::path
instanziiert werden.
boost::filesystem::path
#include <boost/filesystem.hpp>
using namespace boost::filesystem;
int main()
{
path p1{"..."};
path p2{"\\"};
path p3{"@:"};
}
Beispiel 35.2 kann ohne Probleme ausgeführt werden, weil Pfadangaben letztendlich nur Strings sind. Die Klasse boost::filesystem::path
macht nichts anderes als Strings zu verarbeiten. Es finden keine Zugriffe aufs Dateisystem statt.
Da boost::filesystem::path
Strings verarbeitet, stehen Methoden bereit, um eine Pfadangabe als String zu erhalten. Interessanterweise stehen dazu eine ganze Reihe von Methoden zur Verfügung.
Boost.Filesystem unterscheidet grundsätzlich zwischen nativen und generischen Pfadangaben. Native Pfadangaben sind betriebssystemspezifisch und müssen verwendet werden, wenn zum Beispiel Betriebssystemfunktionen aufgerufen werden. Generische Pfadangaben sind portabel und betriebssystemunabhängig.
boost::filesystem::path
als Strings erhalten#include <boost/filesystem.hpp>
#include <iostream>
using namespace boost::filesystem;
int main()
{
path p{"C:\\Windows\\System"};
#ifdef BOOST_WINDOWS_API
std::wcout << p.native() << '\n';
#else
std::cout << p.native() << '\n';
#endif
std::cout << p.string() << '\n';
std::wcout << p.wstring() << '\n';
std::cout << p.generic_string() << '\n';
std::wcout << p.generic_wstring() << '\n';
}
Die ersten drei aufgerufenen Methoden native()
, string()
und wstring()
geben die Pfadangabe im nativen Format zurück. Wenn Sie Beispiel 35.3 unter Windows ausführen, wird dreimal C:\Windows\System
ausgegeben – eine Pfadangabe, wie Sie unter Windows üblich ist.
Die letzten beiden aufgerufenen Methoden generic_string()
und generic_wstring()
geben die Pfadangabe im generischen Format zurück. Dabei handelt es sich um eine portable Pfadangabe – der String wird normalisiert. Die Regeln, nach denen generische Pfadangaben gebildet werden, entsprechen denen des POSIX-Standards. Generische Pfadangaben sind daher identisch mit Pfadangaben, wie sie beispielsweise unter Linux verwendet werden. So wird zum Beispiel als Trennzeichen für Verzeichnisse der Schrägstrich verwendet. Beispiel 35.3 unter Windows ausgeführt gibt für generic_string()
und generic_wstring()
C:/Windows/System
aus.
Der Rückgabewert von Methoden für native Pfadangaben hängt davon ab, unter welchem Betriebssystem ein Programm ausgeführt wird. Der Rückgabewert von Methoden für generische Pfadangaben ist unabhängig vom Betriebssystem. Somit helfen generische Pfadangaben, plattformunabhängigen Code zu schreiben, da sie unabhängig vom Betriebssystem Dateien und Verzeichnisse eindeutig identifizieren.
Da boost::filesystem::path
mit unterschiedlichen String-Typen initialisiert werden kann, werden entsprechend mehrere Methoden angeboten, um Pfadangaben in unterschiedlichen String-Typen zu erhalten. Während string()
und generic_string()
einen String vom Typ std::string
zurückgeben, geben wstring()
und generic_wstring()
einen String vom Typ std::wstring
zurück.
Der Typ des Rückgabewerts von native()
hängt vom Betriebssystem ab, für das das Programm kompiliert wird. So gibt native()
unter Windows einen String vom Typ std::wstring
und unter Linux einen String vom Typ std::string
zurück.
Beachten Sie, dass der Konstruktor von boost::filesystem::path
sowohl generische als auch plattformabhängige Pfadangaben unterstützt. Die Angabe „C:\\Windows\\System“, die im obigen Programm verwendet wird, ist nicht portabel, sondern windows-spezifisch. Sie wird von Boost.Filesystem richtig interpretiert, wenn das Programm unter Windows ausgeführt wird. Das gleiche Programm auf einem POSIX-System wie Linux ausgeführt gibt für alle Methodenaufrufe C:\Windows\System
zurück. Denn in diesem Fall erkennt Boost.Filesystem nicht, dass der Backslash als Trennzeichen für Dateien und Verzeichnisse verwendet werden soll: Er ist weder im portablen noch im nativen Format unter Linux ein Trennzeichen.
Das Makro BOOST_WINDOWS_API
stammt aus Boost.System und ist definiert, wenn das Beispiel unter Windows kompiliert wird. Das entsprechende Makro für POSIX-Betriebssysteme lautet BOOST_POSIX_API
.
Im Beispiel 35.4 findet die Initialisierung mit einem portablen Pfad statt.
boost::filesystem::path
mit portablem Pfad initialisieren#include <boost/filesystem.hpp>
#include <iostream>
using namespace boost::filesystem;
int main()
{
path p{"/"};
std::cout << p.string() << '\n';
std::cout << p.generic_string() << '\n';
}
Da generic_string()
einen portablen Pfad zurückgibt, ist das in diesem Fall genau die Angabe, mit der boost::filesystem::path
initialisiert wurde – also „/“. Die Methode string()
kann jedoch je nach Plattform unterschiedliche Werte zurückgeben. Unter Windows und Linux gibt diese Methode als Ergebnis „/“ zurück. Das Ergebnis ist für diese beiden Plattformen identisch, weil auch Windows den Schrägstrich als Trennzeichen für Verzeichnisse akzeptiert, auch wenn der Backslash das bevorzugte Trennzeichen ist.
boost::filesystem::path
bietet mehrere Methoden an, um auf bestimmte Teile eines Pfads zuzugreifen.
#include <boost/filesystem.hpp>
#include <iostream>
using namespace boost::filesystem;
int main()
{
path p{"C:\\Windows\\System"};
std::cout << p.root_name() << '\n';
std::cout << p.root_directory() << '\n';
std::cout << p.root_path() << '\n';
std::cout << p.relative_path() << '\n';
std::cout << p.parent_path() << '\n';
std::cout << p.filename() << '\n';
}
Wenn Beispiel 35.5 unter Windows ausgeführt wird, wird der String „C:\\Windows\\System“ als plattformabhängige Pfadangabe interpretiert. Daraufhin gibt root_name()
"C:"
zurück, root_directory()
"\"
, root_path()
"C:\"
, relative_path()
"Windows\System"
, parent_path()
"C:\Windows"
und filename()
"System"
.
Die im Beispiel aufgerufenen Methoden geben plattformabhängige Pfadangaben zurück. boost::filesystem::path
speichert Pfadangaben intern im plattformabhängigen Format. Möchten Sie Pfadangaben im portablen Format erhalten, müssen Sie explizit Methoden wie generic_string()
aufrufen.
Wenn Sie Beispiel 35.5 unter Linux ausführen, erhalten Sie andere Werte. So geben fast alle Methoden eine leere Zeichenkette zurück. Einzige Ausnahme sind relative_path()
und filename()
, die jeweils "C:\Windows\System"
zurückgeben. Die Angabe „C:\\Windows\\System“ wird demnach unter Linux als ein Dateiname interpretiert. Das ist insofern verständlich als dass es sich hierbei weder um eine portable Kodierung einer Pfadangabe noch um eine von Linux unterstützte plattformabhängige Kodierung handelt. Boost.Filesystem bleibt unter Linux nichts anderes übrig als die gesamte Angabe als Dateinamen zu interpretieren.
Boost.Filesystem bietet zusätzlich Methoden an, mit denen sich ermitteln lässt, ob das betreffende Teilstück in einem Pfad existiert. Diese Methoden lauten has_root_name()
, has_root_directory()
, has_root_path()
, has_relative_path()
, has_parent_path()
und has_filename()
. Sie alle haben einen Rückgabewert vom Typ bool
.
Es gibt zwei weitere Methoden, mit denen ein Dateiname in seine Bestandteile zerlegt wird. Diese Methoden sollten nur dann aufgerufen werden, wenn has_filename()
true
zurückgibt. Ansonsten werden leere Strings zurückgegeben – wo kein Dateiname, kann nichts zerlegt werden.
#include <boost/filesystem.hpp>
#include <iostream>
using namespace boost::filesystem;
int main()
{
path p{"photo.jpg"};
std::cout << p.stem() << '\n';
std::cout << p.extension() << '\n';
}
Beispiel 35.6 gibt für stem()
"photo"
und für extension()
".jpg"
zurück.
Es ist auch möglich, über Bestandteile eines Pfads zu iterieren.
#include <boost/filesystem.hpp>
#include <iostream>
using namespace boost::filesystem;
int main()
{
path p{"C:\\Windows\\System"};
for (const path &pp : p)
std::cout << pp << '\n';
}
Beispiel 35.7 gibt nacheinander "C:"
, "/"
, "Windows"
und "System"
aus – wenn das Programm unter Windows ausgeführt wird. Auf einem anderen Betriebssystem wie Linux lautet die Ausgabe "C:\Windows\System"
.
Nachdem Sie mehrere Methoden kennengelernt haben, um auf verschiedene Bestandteile eines Pfads zuzugreifen, lernen Sie im Beispiel 35.8 eine Methode kennen, mit der eine Pfadangabe geändert werden kann.
operator/=
aneinanderhängen#include <boost/filesystem.hpp>
#include <iostream>
using namespace boost::filesystem;
int main()
{
path p{"C:\\"};
p /= "Windows\\System";
std::cout << p.string() << '\n';
}
Im Beispiel 35.8 wird mit Hilfe des überladenen Operators operator/=
ein Pfad an einen anderen gehängt. Das Beispiel gibt daher C:\Windows\System
aus – unter Windows. Unter Linux wird C:\/Windows\System
ausgegeben, da unter Linux der Schrägstrich das Trennzeichen für Dateien und Verzeichnisse ist. Dieser Schrägstrich ist auch der Grund, warum der Operator operator/=
überladen wurde.
Neben operator/=
bietet Boost.Filesystem zum Ändern einer Pfadangabe lediglich die Methoden remove_filename()
, replace_extension()
und make_preferred()
an. Letztgenannte Methode ist speziell für den Einsatz unter Windows gedacht.
make_preferred()
#include <boost/filesystem.hpp>
#include <iostream>
using namespace boost::filesystem;
int main()
{
path p{"C:/Windows/System"};
std::cout << p.make_preferred() << '\n';
}
Auch wenn Pfadangaben unter Windows normalerweise den Backslash als Trennzeichen verwenden, akzeptiert Windows den Schrägstrich. So ist „C:/Windows/System“ eine gültige native Pfadangabe unter Windows. Mit make_preferred()
kann die Pfadangabe in die bevorzugte Schreibweise umgewandelt werden. So gibt Beispiel 35.9 "C:\Windows\System"
aus.
Unter Linux und anderen POSIX-Plattformen ändert make_preferred()
eine Pfadangabe nicht.
Beachten Sie, dass make_preferred()
nicht nur die geänderte Pfadangabe zurückgibt, sondern auch das Objekt ändert, für das die Methode aufgerufen wird. Die nach dem Methodenaufruf intern in p gespeicherte Pfadangabe ist „C:\Windows\System“.