27.02.2011

Verwendung von Dateipfaden bei Objective-C

Im Folgenden wird an ein paar Beispielen erklärt, mit welchen Hilfsmethoden einfach mit Dateipfaden umgegangen werden kann. Beispielsweise das Zerlegen von Pfaden, Zugriff auf das Parent-Verzeichnis, Inhalt eines Verzeichnisses, usw.

Zerlegen von Dateipfaden

Man ist oft in der Situation einen Dateipfad in seine Bestandteile zu zerlegen. Beispielsweise, um aus den Bestandteilen einen neuen leicht veränderten Pfad zusammenzubauen. Wenn man aus der Java-Welt kommt, denkt man zuerst an java.io.File oder java.util.StringTokenizer. Dort wird man bei Objective-C allerdings nicht fündig. Die gesuchten Methoden befinden sind in der Klasse NSString. Dort existiert eine Methode pathComponents, die einen Dateipfad in seine Bestandteile zerlegt und ein NSArray zurückliefert.

Um den Dateipfad /Library/Fonts zu zerlegen, kann der folgende Quellcode verwendet werden:

NSString *path = @"/Library/Fonts";
NSArray * components = [path pathComponents];
for(id c in components) {
    NSLog(@"%@", c);
}

Als Ausgabe erhält man folgendes:

2011-02-27 08:31:04.886 FileHandling[14855:a0f] /
2011-02-27 08:31:04.889 FileHandling[14855:a0f] Library
2011-02-27 08:31:04.890 FileHandling[14855:a0f] Fonts

Existenzprüfung von Dateien

Wenn eine Datei geladen werden soll, ist es sinnvoll, vorher zu überprüfen, ob sie vorhanden ist. Dazu bietet die Klasse NSFileManager die Methode fileExistsAtPath:. Die Methode bekommt als Parameter einen Pfad als String übergeben.

In dem folgenden Beispiel soll überprüft werden, ob eine bestimmte Schriftart im Fonts-Ordner abgelegt ist.

NSString *filePath = @"/Library/Fonts/Arial Bold.ttf";
NSFileManager *fileManager = [NSFileManager defaultManager];
BOOL fileExists = [fileManager fileExistsAtPath:filePath];
NSLog(@"File exists: %i", fileExists);

In dem Beispiel sollte als Ausgabe der Wert 1 erscheinen, weil die Datei in dem angegebenen Verzeichnis existiert.

Bestimmung des absoluten Dateipfads

In dem Beispiel Existenzprüfung von Dateien ist davon ausgegangen worden, daß der Dateipfad vollständig bekannt ist. Leider ist das nicht immer so. Oft kennt man den absoluten Dateipfad, der für die Überprüfung notwendig ist, nicht. Wenn dann versucht wird den Pfad mit Hilfe des Finders zu bestimmen, wird es auch Probleme geben, weil Teile des Pfads von Mac OSX lokalisiert wurden. Eine naheliegene Lösung ist, die Datei per Drag&Drop in Xcode zu ziehen. Damit erhält man einen Pfad in der Form file://localhost/Users/joern/Documents/22.02.11 18-42-05.tcx. Leider läßt sich die Existenzprüfung einer Datei auch damit nicht durchführen. Ein weiterer Ansatz ist den vorderen Teil des Pfad wegzulassen und einen relativen Pfad anzugeben. Beispielsweise in der Form ~/Documents/22.02.11 18-42-05.tcx. Dies funktioniert allerdings auch nicht. Glücklicherweise stellt die Klasse NSString die Methode stringByResolvingSymlinksInPath zur Verfügung. Mit dieser Methode lassen sich die symbolischen Links innerhalb eines Pfades auflösen. Beispielsweise wird aus dem Pfad ~/Documents/22.02.11 18-42-05.tcx der Dateipfad /Users/joern/Documents/22.02.11 18-42-05.tcx.

Hinweis


Das Zeichen ~ (Tilde) erhält man, indem alt-N auf der Tastatur gedrückt wird.

In dem folgenden Beispiel wird überprüft, ob sich die Datei 22.02.11 18-42-05.tcx im Verzeichnis Dokumente befindet. Die erste auskommentierte Zeile ist durch Drag&Drop aus dem Finder entstanden. Die zweite auskommentierte Zeile ist der relative Pfad zu der Datei. Beide Lösungen funktionieren nicht. Erst das Auflösen der symbolischen Links mit der Methode stringByResolvingSymlinksInPath bringt das gewünschte Ergebnis.

//NSString *filePath = @"file://localhost/Users/heike/Documents/22.02.11 18-42-05.tcx"; //Does not work!
//NSString *filePath = @"~/Documents/22.02.11 18-42-05.tcx"; // Does not work!
NSString *filePath = [@"~/Documents/22.02.11 18-42-05.tcx" stringByResolvingSymlinksInPath];
NSFileManager *fileManager = [NSFileManager defaultManager];
BOOL fileExists = [fileManager fileExistsAtPath:filePath];
NSLog(@"File %@ exists: %i", filePath, fileExists);

Die Ausgabe sieht dann ungefähr so aus:

2011-02-27 09:34:02.739 FileHandling[15211:a0f]
   File /Users/joern/Documents/22.02.11 18-42-05.tcx exists: 1

Zugriff auf das Parent-Verzeichnis

Oft tritt der Fall ein, daß man einen vollständigen Pfad zu einer Datei hat, aber nur das Verzeichnis in der sich die Datei befindet für das weitere arbeiten benötigt. Dafür stellt Objective-C die Methode stringByDeletingLastPathComponent: zur Verfügung.

Ausgehend von dem Beispiel in Bestimmung des absoluten Dateipfads wird der Dateipfad filePath um die letzte Pfadkomponente verkürzt.

NSString *filePath = [@"~/Documents/22.02.11 18-42-05.tcx" stringByResolvingSymlinksInPath];
NSString* parentPath = [filePath stringByDeletingLastPathComponent];
NSLog(@"Parent path: %@", parentPath);

Als Ausgabe erhält man folgendes

Parent path: /Users/joern/Documents

Ausgabe aller Dateien eines Verzeichnisses

Oft sollen alle Dateien eines Verzeichnisses verarbeitet werden. Beispielweise möchte man alle Dateien im Verzeichnis Dokumente auf der Konsole ausgeben. Der folgende Quellcode tut genau dies. Mit Hilfe der Methode contentsOfDirectoryAtPath des NSFileManager werden alle Dateien in dem Verzeichnis aufgelistet.

NSError *error = nil;
NSString *path = [@"~/Documents/" stringByResolvingSymlinksInPath];
NSFileManager *manager = [NSFileManager defaultManager];
NSArray *directoryContent =
            [manager contentsOfDirectoryAtPath:path error:&error];
for(id file in directoryContent) {
    NSLog(@"%@", file);
}

Dateipfade zusammenbauen

Eine weitere sehr nützliche Methode der Klasse NSString ist stringByAppendingPathComponent:. Mit ihr lassen sich Dateipfade zusammenbauen. Hat man beispielsweise einen Pfad path, der auf das Dokumente-Verzeichnis zeigt und man weiß, daß sich in dem Verzeichnis die Datei test.txt befindet, dann kann man den Pfad mit Hilfe der Methode stringByAppendingPathComponent um test.txt ergänzen. Vorteil diese Vorgehensweise ist, daß man sich nicht um die Trennzeichen (Slash, Backslash) kümmern muß.

NSString *path = [@"~/Documents/" stringByResolvingSymlinksInPath];
NSString *subpath = [path stringByAppendingPathComponent:@"test.txt"];
NSLog(@"Subpath: %@", subpath);