Dateien in einem Verzeichnis auflisten
Mit der list()-Methode der File-Klasse können Sie ganz einfach die Dateinamen aller Dateien in einem Verzeichnis auflisten. Wenn Sie andere Dateien als nur Dateinamen abrufen möchten, können Sie die Methode listFiles() verwenden. Das ist sehr einfach, das Schwierige ist, wie die zurückgegebene Liste verarbeitet wird. Anstatt herkömmliche, lange externe Iteratoren zu verwenden, verwenden wir elegante Funktionsausdrücke, um diese Liste tatsächlich zu durchlaufen. Hier müssen wir auch die neue CloseableStream-Schnittstelle des JDK und einige verwandte Funktionen höherer Ordnung verwenden.
Der folgende Code listet die Namen aller Dateien im aktuellen Verzeichnis auf.
Kopieren Sie den Codecode wie folgt:
Files.list(Paths.get("."))
.forEach(System.out::println);
Wenn Sie andere Verzeichnisse auflisten möchten, können Sie „.“ durch den vollständigen Pfad des Verzeichnisses ersetzen, auf das Sie zugreifen möchten.
Hier verwenden wir zunächst die Methode get() von Paths, um eine Path-Instanz über einen String zu erstellen. Dann erhalten wir über die list()-Methode der Files-Toolklasse ein ClosableStream-Objekt und können damit alle Dateien im Verzeichnis durchsuchen. Anschließend verwenden wir den internen Iterator forEach(), um den Dateinamen auszugeben. Schauen wir uns zunächst einige der Ausgabeergebnisse dieses Codes an: Listen Sie die Dateien und Unterverzeichnisse im aktuellen Verzeichnis auf.
Kopieren Sie den Codecode wie folgt:
./aSampleFiles.txt
./bin
./fpij
...
Wenn wir nur die Unterverzeichnisse des aktuellen Verzeichnisses und nicht die Dateien abrufen möchten, können wir die Methode filter() verwenden:
Kopieren Sie den Codecode wie folgt:
Files.list(Paths.get("."))
.filter(Files::isDirectory)
.forEach(System.out::println);
Die Methode ilter() filtert Verzeichnisse aus dem Dateistream. Wir übergeben einen Verweis auf die isDirectory-Methode der Files-Klasse, anstatt einen Lambda-Ausdruck zu übergeben. Denken Sie daran, dass die Methode filter() einen Prädikattyp erfordert, der einen booleschen Wert zurückgibt, und diese Methode ist genau richtig. Schließlich verwenden wir einen internen Iterator, um den Namen des Verzeichnisses auszugeben. Das Programm druckt die Unterverzeichnisse des aktuellen Verzeichnisses aus.
Kopieren Sie den Codecode wie folgt:
./bin
./fpij
./Ausgabe
...
Es ist viel einfacher, auf diese Weise zu schreiben und spart viel Code im Vergleich zur alten Schreibweise in Java. Schauen wir uns an, wie man Dateien auflistet, die einem bestimmten Muster entsprechen.
Listen Sie die in einem Verzeichnis angegebenen Dateien auf
Java stellt seit langem eine Variante der list()-Methode zum Filtern von Dateinamen zur Verfügung. Diese Version der list()-Methode akzeptiert einen Parameter vom Typ FilenameFilter. Diese Schnittstelle verfügt nur über eine Methode „accept()“, die zwei Parameter akzeptiert: „Dateiverzeichnis“ (das das Verzeichnis darstellt) und „Stringname“ (das den Dateinamen darstellt). Wenn die Methode „accept()“ „true“ zurückgibt, wird der Dateiname in der zurückgegebenen Liste angezeigt, andernfalls nicht. Lassen Sie uns diese Methode implementieren.
Der übliche Ansatz besteht darin, eine Instanz einer anonymen inneren Klasse, die die FilenameFilter-Schnittstelle implementiert, an die list()-Methode zu übergeben. Schauen wir uns beispielsweise an, wie Sie mit dieser Methode die .java-Datei im FPij-Verzeichnis zurückgeben.
Kopieren Sie den Codecode wie folgt:
finale String[]-Dateien =
new File("fpij").list(new java.io.FilenameFilter() {
public boolean Accept(endgültiges Dateiverzeichnis, endgültiger String-Name) {
return name.endsWith(".java");
}
});
System.out.println(files);
Das Schreiben einiger Codezeilen erfordert wirklich einige Zeit und Mühe. Diese Art von Code ist zu laut: Objekte erstellen, Funktionen aufrufen, anonyme innere Klassen definieren, Methoden in Klassen einbetten usw. Wir müssen diesen Schmerz nicht länger ertragen, sondern übergeben einfach einen Lambda-Ausdruck, der zwei Parameter akzeptiert und einen Bollean-Wert zurückgibt. Den Rest erledigt der Java-Compiler.
Das vorherige Beispiel könnte die anonymen Interna einfach durch einen Lambda-Ausdruck ersetzen, aber es gibt Raum für weitere Optimierung. Das neue DirectoryStream-Tool kann uns dabei helfen, große Verzeichnisstrukturen effizienter zu durchqueren. Probieren wir diese Methode aus. Dies ist eine Variante der newDirectoryStream()-Methode, die einen zusätzlichen Filter akzeptiert.
Kopieren Sie den Codecode wie folgt:
Files.newDirectoryStream(
Paths.get("fpij"), path -> path.toString().endsWith(".java"))
.forEach(System.out::println);
Auf diese Weise werden wir die anonyme innere Klasse los und machen den umständlichen Code prägnant und klar. Die Ausgabe beider Versionen ist gleich. Drucken wir die angegebene Datei aus.
Dieser Code gibt nur .java-Dateien im angegebenen Verzeichnis aus. Hier ist ein Teil seiner Ausgabe:
Kopieren Sie den Codecode wie folgt:
fpij/Compare.java
fpij/IterateString.java
fpij/ListDirs.java
...
Wir filtern Dateien basierend auf Dateinamen. Es kann auch einfach nach Dateiattributen gefiltert werden, z. B. ob die Datei ausführbar, lesbar, beschreibbar usw. ist. Dazu benötigen Sie eine listFiles()-Methode, die einen Parameter vom Typ FileFilter akzeptiert. Wir verwenden immer noch Lambda-Ausdrücke, anstatt anonyme innere Klassen zu erstellen. Schauen wir uns nun ein Beispiel für die Auflistung aller versteckten Dateien im aktuellen Verzeichnis an.
Kopieren Sie den Codecode wie folgt:
final File[] files = new File(".").listFiles(file -> file.isHidden());
Wenn wir ein großes Verzeichnis betreiben, können wir DirectoryStream verwenden, anstatt die Methode für File direkt aufzurufen.
Die Signatur des Lambda-Ausdrucks, den wir an die Methode „listFiles()“ übergeben, ist dieselbe wie die Signatur der Methode „accept()“ der FileFilter-Schnittstelle. Dieser Lambda-Ausdruck akzeptiert einen Parameter einer File-Instanz. In diesem Beispiel lautet der Parametername file. Wenn die Datei versteckte Attribute hat, wird „true“ zurückgegeben, andernfalls wird „false“ zurückgegeben.
Tatsächlich kann der Code hier weiter optimiert werden. Durch die Übergabe einer Methodenreferenz sieht der Code prägnanter aus:
Kopieren Sie den Codecode wie folgt:
neue Datei(".").listFiles(File::isHidden);
Wir haben es zunächst mithilfe von Lambda-Ausdrücken implementiert und es dann mithilfe von Methodenreferenzen umgestaltet, um es prägnanter zu gestalten. Wenn wir neuen Code schreiben, sollten wir natürlich diese prägnante Methode verwenden. Wenn eine so saubere Implementierung frühzeitig gefunden werden könnte, würden wir deren Verwendung sicherlich priorisieren. Es gibt ein Sprichwort namens „Lass es zuerst funktionieren, dann mache es besser“. Nachdem wir es geklärt haben, werden wir die Einfachheit und Leistung berücksichtigen.
Wir verwenden ein Beispiel, um bestimmte Dateien aus einem Verzeichnis herauszufiltern. Schauen wir uns an, wie man die Unterverzeichnisse unter einem bestimmten Verzeichnis durchläuft.