From 33613a85afc4b1481367fbe92a17ee59c240250b Mon Sep 17 00:00:00 2001
From: Sven Eisenhauer
+Wurde ein File-Objekt
+für ein Verzeichnis konstruiert, so stehen weitere Methoden zur
+Verfügung, um auf die zusätzlichen Funktionen eines Verzeichnisses
+zuzugreifen. Mit Hilfe der Methode list
+ist es beispielsweise möglich, den Inhalt des Verzeichnisses
+auszulesen:
+
+
+list
+liefert ein Array von Strings, das für jeden gefundenen Verzeichniseintrag
+ein Element enthält. Die Liste enthält die Namen aller Dateien
+und Unterverzeichnisse mit Ausnahme von .
+und ... list
+gibt es noch in einer zweiten Variante, bei der die Auswahl der Verzeichniseinträge
+eingeschränkt werden kann. Dabei muss ein Objekt übergeben
+werden, das das Interface FilenameFilter
+implementiert. Dieses besitzt eine Methode accept,
+die für jede gefundene Datei aufgerufen wird und entscheidet,
+ob sie in die Liste aufgenommen werden soll oder nicht.
+
+
+Zusätzlich gibt es die statische Methode listRoots,
+mit der eine Liste aller »Wurzeln« der verfügbaren
+Dateisysteme beschafft werden kann. Unter UNIX gibt es lediglich die
+Wurzel »/«, unter Windows dagegen eine für jeden Laufwerksbuchstaben.
+
+
+Eine häufig benötigte Funktion besteht darin, ein Verzeichnis
+samt seiner Unterverzeichnisse rekursiv zu durchlaufen und bei jedem
+gefundenen Eintrag eine bestimmte Aufgabe zu erledigen. Wir wollen
+zeigen, wie mit Hilfe des Visitor-Patterns (siehe Abschnitt 10.4.8)
+eine universell verwendbare Lösung geschaffen werden kann. Zunächst
+definieren wir dazu ein Interface DirectoryVisitor:
+
+
+
+
+
+
+ Titel
+ Inhalt
+ Suchen
+ Index
+ DOC
+ Handbuch der Java-Programmierung, 5. Auflage
+
+ <<
+ <
+ >
+ >>
+ API
+ Kapitel 21 - Datei- und Verzeichnis-Handling
+
+
+
+
+
+21.4 Zugriff auf Verzeichniseinträge
+
+
+
+
+
+
+
+
+21.4.1 Lesen von Verzeichniseinträgen
+
+
+
+
+
+
+
+
+
+
+public String[] list()
+
+
+
+java.io.File
+
+
+
+Listing 21.2: Das Interface DirectoryVisitor
+
+
+
+
+
+001 /* DirectoryVisitor.java */
+002
+003 import java.io.*;
+004
+005 public interface DirectoryVisitor
+006 {
+007 public void enterDirectory(File dir);
+008 public void leaveDirectory(File dir);
+009 public void visitFile(File file);
+010 }
+
+
+DirectoryVisitor.java
+
+Beim Betreten eines Verzeichnisses wird enterDirectory +aufgerufen, beim Verlassen leaveDirectory. +Zu jedem darin enthaltenen Dateieintrag wird visitFile +aufgerufen. Um es der konkreten Visitor-Implementierung so einfach +wie möglich zu machen, werden sowohl Verzeichnisse als auch Dateien +als fertige File-Objekte +übergeben. + +
+Ein konkreter Visitor, der eine Verzeichnisstruktur mit den darin +enthaltenen Dateien und Unterverzeichnissen korrekt eingerückt +auf dem Bildschirm ausgibt, entsteht durch Implementieren von DirectoryVisitor +wie folgt: + + +
+
+
+
+001 /* DirectoryPrintVisitor.java */
+002
+003 import java.io.*;
+004
+005 public class DirectoryPrintVisitor
+006 implements DirectoryVisitor
+007 {
+008 String indent = "";
+009
+010 public void enterDirectory(File dir)
+011 {
+012 System.out.println(indent + "[" + dir.getName() + "]");
+013 indent += " ";
+014 }
+015
+016 public void leaveDirectory(File dir)
+017 {
+018 indent = indent.substring(2);
+019 }
+020
+021 public void visitFile(File file)
+022 {
+023 System.out.println(indent + file.getName());
+024 }
+025 }
+
+ |
++DirectoryPrintVisitor.java | +
+In ähnlicher Weise kann ein DirectoryVisitor +geschrieben werden, der die Anzahl der Dateien und Verzeichnisse zählt +und die kumulierte Größe der darin enthaltenen Dateien +ermittelt: + + +
+
+
+
+001 /* DirectorySizeVisitor.java */
+002
+003 import java.io.*;
+004
+005 public class DirectorySizeVisitor
+006 implements DirectoryVisitor
+007 {
+008 int files = 0;
+009 int dirs = 0;
+010 long size = 0;
+011
+012 public void enterDirectory(File dir)
+013 {
+014 ++dirs;
+015 }
+016
+017 public void leaveDirectory(File dir)
+018 {
+019 }
+020
+021 public void visitFile(File file)
+022 {
+023 ++files;
+024 size += file.length();
+025 }
+026
+027 public int getDirs()
+028 {
+029 return dirs;
+030 }
+031
+032 public int getFiles()
+033 {
+034 return files;
+035 }
+036
+037 public long getSize()
+038 {
+039 return size;
+040 }
+041 }
+
+ |
++DirectorySizeVisitor.java | +
+Nun fehlen nur noch die generische Methode für den rekursiven +Verzeichnisdurchlauf und ein Beispielprogramm, das die Anwendung der +Klassen im Zusammenspiel zeigt: + + +
+
+
+
+001 /* Listing2105.java */
+002
+003 import java.io.*;
+004
+005 public class Listing2105
+006 {
+007 static void traverse(File dir, DirectoryVisitor visitor)
+008 {
+009 if (!dir.isDirectory()) {
+010 throw new IllegalArgumentException(
+011 "not a directory: " + dir.getName()
+012 );
+013 }
+014 visitor.enterDirectory(dir);
+015 File[] entries = dir.listFiles(
+016 new FileFilter()
+017 {
+018 public boolean accept(File pathname)
+019 {
+020 return true;
+021 }
+022 }
+023 );
+024 for (int i = 0; i < entries.length; ++i) {
+025 if (entries[i].isDirectory()) {
+026 traverse(entries[i], visitor);
+027 } else {
+028 visitor.visitFile(entries[i]);
+029 }
+030 }
+031 visitor.leaveDirectory(dir);
+032 }
+033
+034 public static void main(String[] args)
+035 {
+036 File file = new File(args[0]);
+037 //Bildschirmausgabe der Struktur
+038 traverse(file, new DirectoryPrintVisitor());
+039 //Größen ermitteln
+040 DirectorySizeVisitor visitor = new DirectorySizeVisitor();
+041 traverse(file, visitor);
+042 System.out.println("directories: " + visitor.getDirs());
+043 System.out.println("files: " + visitor.getFiles());
+044 System.out.println("size: " + visitor.getSize());
+045 }
+046 }
+
+ |
++Listing2105.java | +
+Die eigentliche Arbeit wird von traverse +erledigt. Sie stellt zunächst sicher, dass das übergebene +File-Objekt +auch tatsächlich ein Verzeichnis darstellt, und nicht etwa eine +Datei. Ist das der Fall, wird auf dem übergebenen Visitor enterDirectory +aufgerufen und mit listFiles +eine Liste aller im Verzeichnis enthaltenen Dateien und Unterverzeichnisse +beschafft. Zu jedem Unterverzeichnis erfolgt ein rekursiver Aufruf +von traverse, zu jeder Datei +wird visitFile aufgerufen. Nachdem +alle Einträge abgearbeitet sind, wird das dem Visitor durch Aufruf +von leaveDirectory mitgeteilt. +
+
![]() |
+![]() |
+
+
+ +Die Methode listFiles +gibt es seit der Version 1.2 im JDK. Muß für eine ältere +JDK-Version entwickelt werden, kann alternativ list +verwendet werden. Diese gibt allerdings kein File-, +sondern ein String-Array +zurück. |
+
+
|
+![]() |
+
+Neben dem Zugriff auf die Verzeichniseinträge gibt es in der +Klasse File +auch Methoden, um Dateien oder Verzeichnisse zu löschen oder +umzubenennen und um Verzeichnisse neu anzulegen: +
+
+
++public boolean mkdir() +public boolean mkdirs() + +public boolean renameTo(File dest) + +public boolean delete() ++ + |
++java.io.File | +
+Die Methode delete +löscht die durch das File-Objekt +bezeichnete Datei. Mit renameTo +wird das File-Objekt +in das als Parameter übergebene Objekt umbenannt. Durch Aufruf +von mkdir +wird das durch das File-Objekt +spezifizierte Verzeichnis angelegt. Mit mkdirs +werden sogar alle Vaterverzeichnisse automatisch angelegt, wenn sie +noch nicht existieren. Alle Methoden geben true +zurück, wenn sie ihre Aufgabe erfolgreich ausführen konnten. +Andernfalls geben sie false +zurück. + +
+Das folgende Listing zeigt die Verwendung der Klasse File +und den Aufruf verschiedener Methoden: + + +
+
+
+
+001 /* TestFile.java */
+002
+003 import java.io.*;
+004 import java.util.*;
+005
+006 public class TestFile
+007 {
+008 public static void main(String[] args)
+009 {
+010 File fil = new File("TestFile.java");
+011 TestFile.printFileInfo(fil);
+012 fil = new File("..");
+013 TestFile.printFileInfo(fil);
+014 }
+015
+016 static void printFileInfo(File fil)
+017 {
+018 System.out.println("Name= "+fil.getName());
+019 System.out.println("Path= "+fil.getPath());
+020 System.out.println("AbsolutePath= "+fil.getAbsolutePath());
+021 System.out.println("Parent= "+fil.getParent());
+022 System.out.println("exists= "+fil.exists());
+023 System.out.println("canWrite= "+fil.canWrite());
+024 System.out.println("canRead= "+fil.canRead());
+025 System.out.println("isFile= "+fil.isFile());
+026 System.out.println("isDirectory= "+fil.isDirectory());
+027 if (fil.isDirectory()) {
+028 String[] fils = fil.list();
+029 for (int i=0; i<fils.length; ++i) {
+030 System.out.println(" "+fils[i]);
+031 }
+032 }
+033 System.out.println("isAbsolute= "+fil.isAbsolute());
+034 System.out.println(
+035 "lastModified= "+(new Date(fil.lastModified()))
+036 );
+037 System.out.println("length= "+fil.length());
+038 System.out.println("");
+039 }
+040 }
+
+ |
++TestFile.java | +
+Ein Aufruf des Programms liefert folgende Ausgabe:
+
+
+Name= TestFile.java
+Path= TestFile.java
+AbsolutePath= C:\ARC\DOKU\java\examples\TestFile.java
+Parent= null
+exists= true
+canWrite= true
+canRead= true
+isFile= true
+isDirectory= false
+isAbsolute= false
+lastModified= Sun Jan 05 17:15:56 1997
+length= 1242
+
+Name= ..
+Path= ..
+AbsolutePath= C:\ARC\DOKU\java\examples\..
+Parent= null
+exists= true
+canWrite= true
+canRead= true
+isFile= false
+isDirectory= true
+ makefile
+ html.cfg
+ ...
+ jdbc.sgml
+ tuning.sgml
+ reflection.sgml
+isAbsolute= false
+lastModified= Wed Jul 22 16:55:32 GMT+02:00 1998
+length= 0
+
+
+
| Titel + | Inhalt + | Suchen + | Index + | DOC + | Handbuch der Java-Programmierung, 5. Auflage, Addison +Wesley, Version 5.0.1 + |
| << + | < + | > + | >> + | API + | © 1998, 2007 Guido Krüger & Thomas +Stark, http://www.javabuch.de + |