Die Boost C++ Bibliotheken

Dateien und Verzeichnisse

Die Methoden, die Ihnen im Zusammenhang mit der Klasse boost::filesystem::path vorgestellt wurden, tun nichts anderes als Strings zu verarbeiten. So können Sie auf Teilbereiche eines Pfads zugreifen oder einen Pfad an einen anderen hängen. Intern werden in der Klasse boost::filesystem::path einfach nur Strings verarbeitet.

Um tatsächlich auf Dateien und Verzeichnisse zugreifen zu können, stehen zahlreiche freistehende Funktionen zur Verfügung. Diese erwarten als Parameter ein oder mehrere Objekte vom Typ boost::filesystem::path und rufen für die derart identifizierten Dateien oder Verzeichnisse Betriebssystemfunktionen auf.

Bevor verschiedene Funktionen zum Datei- und Verzeichniszugriff vorgestellt werden, erfahren Sie, was im Falle eines Fehlers passiert. Denn alle Funktionen, die Sie kennenlernen werden, greifen auf Betriebssystemfunktionen zu, die fehlschlagen können. Boost.Filesystem bietet von allen Funktionen zwei Varianten an, deren Verhalten sich im Fehlerfall unterscheidet:

boost::system::system_error und boost::system::error_code werden im Kapitel 55 vorgestellt. boost::filesystem::filesystem_error bietet zusätzlich zu der von boost::system::system_error geerbten Schnittstelle die Methoden path1() und path2() an. Beide geben ein Objekt vom Typ boost::filesystem::path zurück. Da es Funktionen gibt, die als Parameter zwei Objekte vom Typ boost::filesystem::path erwarten, stehen entsprechend zwei Methoden zur Verfügung. So können im Fehlerfall die Pfadangaben einfach ermittelt werden.

Im Beispiel 35.10 lernen Sie eine Funktion kennen, mit der der Status einer Datei oder eines Verzeichnisses abgefragt werden kann.

Beispiel 35.10. Dateistatus mit boost::filesystem::status() abfragen
#include <boost/filesystem.hpp>
#include <iostream>

using namespace boost::filesystem;

int main()
{
  path p{"C:\\"};
  try
  {
    file_status s = status(p);
    std::cout << std::boolalpha << is_directory(s) << '\n';
  }
  catch (filesystem_error &e)
  {
    std::cerr << e.what() << '\n';
  }
}

boost::filesystem::status() gibt ein Objekt vom Typ boost::filesystem::file_status zurück. Sie können dieses Objekt an verschiedene Hilfsfunktionen übergeben, um es auszuwerten. So gibt boost::filesystem::is_directory() true zurück, wenn der Status für ein Verzeichnis ermittelt wurde. Neben boost::filesystem::is_directory() stehen weitere Funktionen wie boost::filesystem::is_regular_file(), boost::filesystem::is_symlink() und boost::filesystem::exists() zur Verfügung, die alle einen Rückgabewert vom Typ bool besitzen.

Neben boost::filesystem::status() existiert eine zweite Funktion boost::filesystem::symlink_status(). Diese kann eingesetzt werden, wenn der Status einer Datei ermittelt werden soll, die eine symbolische Verknüpfung ist. Wenn für eine derartige Datei boost::filesystem::status() aufgerufen wird, wird der Status für die Datei ermittelt, auf die die symbolische Verknüpfung verweist. Unter Windows sind Dateien, die symbolische Verknüpfungen darstellen, an der Endung lnk zu erkennen.

Neben den eben vorgestellten Status-Funktionen gibt es eine andere Kategorie von Funktionen, mit denen Attribute ermittelt werden können.

Beispiel 35.11. Dateigröße mit boost::filesystem::file_size() ermitteln
#include <boost/filesystem.hpp>
#include <iostream>

using namespace boost::filesystem;

int main()
{
  path p{"C:\\Windows\\win.ini"};
  boost::system::error_code ec;
  boost::uintmax_t filesize = file_size(p, ec);
  if (!ec)
    std::cout << filesize << '\n';
  else
    std::cout << ec << '\n';
}

Die Funktion boost::filesystem::file_size() gibt die Größe einer Datei in Bytes zurück. Der Rückgabewert hat den Typ boost::uintmax_t, der aus der Bibliothek Boost.Integer stammt.

Im Beispiel 35.11 wird außerdem ein Objekt vom Typ boost::system::error_code verwendet, das explizit ausgewertet werden muss, um zu überprüfen, ob der Aufruf von boost::filesystem::file_size() fehlschlug.

Beispiel 35.12. Zugriffszeit mit boost::filesystem::last_write_time() ermitteln
#include <boost/filesystem.hpp>
#include <iostream>
#include <ctime>

using namespace boost::filesystem;

int main()
{
  path p{"C:\\Windows\\win.ini"};
  try
  {
    std::time_t t = last_write_time(p);
    std::cout << std::ctime(&t) << '\n';
  }
  catch (filesystem_error &e)
  {
    std::cerr << e.what() << '\n';
  }
}

Um den Zeitpunkt zu ermitteln, wann eine Datei das letzte Mal geändert wurde, kann die im Beispiel 35.12 verwendete Funktion boost::filesystem::last_write_time() aufgerufen werden.

Beispiel 35.13. Verfügbarer Speicherplatz mit boost::filesystem::space() ermitteln
#include <boost/filesystem.hpp>
#include <iostream>

using namespace boost::filesystem;

int main()
{
  path p{"C:\\"};
  try
  {
    space_info s = space(p);
    std::cout << s.capacity << '\n';
    std::cout << s.free << '\n';
    std::cout << s.available << '\n';
  }
  catch (filesystem_error &e)
  {
    std::cerr << e.what() << '\n';
  }
}

Mit der im Beispiel 35.13 aufgerufenen Funktion boost::filesystem::space() kann der insgesamt zur Verfügung stehende und momentan noch freie Speicherplatz erhalten werden. Die Funktion gibt ein Objekt vom Typ boost::filesystem::space_info zurück, das drei Eigenschaften capacity, free und available definiert. Alle drei Eigenschaften sind vom Typ boost::uintmax_t. Der Speicherplatz wird in Bytes gemessen.

Während die bisher vorgestellten Funktionen Dateien und Verzeichnisse unberührt lassen, existieren zahlreiche Funktionen, mit denen Dateien und Verzeichnisse erstellt, umbenannt oder gelöscht werden können.

Beispiel 35.14. Verzeichnis erstellen, umbenennen und entfernen
#include <boost/filesystem.hpp>
#include <iostream>

using namespace boost::filesystem;

int main()
{
  path p{"C:\\Test"};
  try
  {
    if (create_directory(p))
    {
      rename(p, "C:\\Test2");
      boost::filesystem::remove("C:\\Test2");
    }
  }
  catch (filesystem_error &e)
  {
    std::cerr << e.what() << '\n';
  }
}

Beispiel 35.14 sollte selbsterklärend sein. Den verschiedenen Funktionen wird jedoch nicht immer ein Objekt vom Typ boost::filesystem::path übergeben, sondern teilweise einfach nur ein String. Das ist insofern kein Problem als dass boost::filesystem::path einen nicht-expliziten Konstruktor anbietet, so dass Strings automatisch in Objekte vom Typ boost::filesystem::path umgewandelt werden. Das macht es einfacher, die vielen Funktionen von Boost.Filesystem zu verwenden, da nicht selbst explizit Objekte vom Typ boost::filesystem::path erstellt werden müssen.

Anmerkung

boost::filesystem::remove() wird im Beispiel 35.14 explizit über ihren Namensraum aufgerufen, da Visual C++ 2013 die Funktion andernfalls mit remove() aus der Headerdatei stdio.h verwechselt.

Neben den im Beispiel 35.14 verwendeten Funktionen stehen auch Funktionen wie create_symlink() zur Verfügung, mit der sich symbolische Verknüpfungen erstellen lassen, oder copy_file(), mit der eine Datei oder ein Verzeichnis kopiert werden kann.

Im Beispiel 35.15 wird Ihnen eine Funktion vorgestellt, die ausgehend von einem Dateinamen oder Teilausschnitt eines Pfads einen absoluten Pfad erstellt.

Beispiel 35.15. Absoluten Pfad mit boost::filesystem::absolute() erstellen
#include <boost/filesystem.hpp>
#include <iostream>

using namespace boost::filesystem;

int main()
{
  try
  {
    std::cout << absolute("photo.jpg") << '\n';
  }
  catch (filesystem_error &e)
  {
    std::cerr << e.what() << '\n';
  }
}

Welcher Pfad ausgegeben wird, hängt davon ab, in welchem Verzeichnis das Programm gestartet wird. Wird es zum Beispiel in C:\ ausgeführt, gibt Beispiel 35.15 "C:\photo.jpg" aus.

Wenn Sie einen absoluten Pfad relativ zu einem anderen Verzeichnis erhalten möchten, können Sie boost::filesystem::absolute() einen zweiten Parameter übergeben.

Beispiel 35.16. Absoluten Pfad relativ zu einem anderen Verzeichnis erstellen
#include <boost/filesystem.hpp>
#include <iostream>

using namespace boost::filesystem;

int main()
{
  try
  {
    std::cout << absolute("photo.jpg", "D:\\") << '\n';
  }
  catch (filesystem_error &e)
  {
    std::cerr << e.what() << '\n';
  }
}

Beispiel 35.16 gibt "D:\photo.jpg" aus.

Abschließend soll Ihnen eine nützliche Hilfsfunktion vorgestellt werden, mit der sich das aktuelle Arbeitsverzeichnis ermitteln lässt.

Beispiel 35.17. Arbeitsverzeichnis mit boost::filesystem::current_path() erhalten
#include <boost/filesystem.hpp>
#include <iostream>

using namespace boost::filesystem;

int main()
{
  try
  {
    std::cout << current_path() << '\n';
    current_path("C:\\");
    std::cout << current_path() << '\n';
  }
  catch (filesystem_error &e)
  {
    std::cerr << e.what() << '\n';
  }
}

Beispiel 35.17 ruft mehrfach boost::filesystem::current_path() auf. Wird die Funktion ohne Parameter aufgerufen, gibt sie das aktuelle Arbeitsverzeichnis zurück. Wird ihr ein Parameter vom Typ boost::filesystem::path übergeben, wird das Arbeitsverzeichnis neu gesetzt.