Löschen Sie ein Verzeichnis rekursiv in Java

Ein Verzeichnis in Java rekursiv löschen

1. Einführung

In diesem Artikel wird veranschaulicht, wie ein Verzeichnis in einfachem Java rekursiv gelöscht wird. Wir werden uns auch einige Alternativen zum Löschen von Verzeichnissen mithilfe externer Bibliotheken ansehen.

2. Verzeichnis rekursiv löschen

Java hat die Option, ein Verzeichnis zu löschen. Dies setzt jedoch voraus, dass das Verzeichnis leer ist. Wir müssen also die Rekursion verwenden, um ein bestimmtes nicht leeres Verzeichnis zu löschen:

  1. Liefert den gesamten Inhalt des zu löschenden Verzeichnisses

  2. Löschen Sie alle untergeordneten Elemente, die kein Verzeichnis sind (Verlassen der Rekursion).

  3. Beginnen Sie für jedes Unterverzeichnis des aktuellen Verzeichnisses mit Schritt 1 (rekursiver Schritt).

  4. Löschen Sie das Verzeichnis

Implementieren wir diesen einfachen Algorithmus:

boolean deleteDirectory(File directoryToBeDeleted) {
    File[] allContents = directoryToBeDeleted.listFiles();
    if (allContents != null) {
        for (File file : allContents) {
            deleteDirectory(file);
        }
    }
    return directoryToBeDeleted.delete();
}

Diese Methode kann mit einem einfachen Testfall getestet werden:

@Test
public void givenDirectory_whenDeletedWithRecursion_thenIsGone()
  throws IOException {

    Path pathToBeDeleted = TEMP_DIRECTORY.resolve(DIRECTORY_NAME);

    boolean result = deleteDirectory(pathToBeDeleted.toFile());

    assertTrue(result);
    assertFalse(
      "Directory still exists",
      Files.exists(pathToBeDeleted));
}

Die Methode@Before unserer Testklasse erstellt einen Verzeichnisbaum mit Unterverzeichnissen und Dateien am SpeicherortpathToBeDeleted, und die Methode@Afterbereinigt das Verzeichnis bei Bedarf.

Als nächstes schauen wir uns an, wie wir das Löschen mit zwei der am häufigsten verwendeten Bibliotheken erreichen können - Apachescommons-ioundspring-core.von Spring Framework. Mit beiden Bibliotheken können wir die Verzeichnisse mit nur einer einzigen Zeile löschen von Code.

3. Verwenden vonFileUtils auscommons-io

Zuerst müssen wir die Abhängigkeit voncommons-iozum Maven-Projekt hinzufügen:


    commons-io
    commons-io
    2.5

Die neueste Version der Abhängigkeit befindet sich inhere.

Jetzt können wirFileUtils verwenden, um alle dateibasierten Operationen einschließlichdeleteDirectory() mit nur einer Anweisung auszuführen:

FileUtils.deleteDirectory(file);

4. Verwenden vonFileSystemUtils aus Spring

Alternativ können wir die Abhängigkeit von spring-corezum Maven-Projekt hinzufügen:


    org.springframework
    spring-core
    4.3.10.RELEASE

Die neueste Version der Abhängigkeit befindet sich inhere.

Wir können diedeleteRecursively()-Methode inFileSystemUtils verwenden, um das Löschen durchzuführen:

boolean result = FileSystemUtils.deleteRecursively(file);

Die jüngsten Versionen von Java bieten neuere Möglichkeiten, solche in den folgenden Abschnitten beschriebenen E / A-Vorgänge auszuführen.

5. Verwenden von NIO2 mit Java 7

Java 7 führte eine völlig neue Methode zur Ausführung von Dateioperationen mitFiles ein. Es ermöglicht uns, einen Verzeichnisbaum zu durchlaufen und Rückrufe für auszuführende Aktionen zu verwenden.

public void whenDeletedWithNIO2WalkFileTree_thenIsGone()
  throws IOException {

    Path pathToBeDeleted = TEMP_DIRECTORY.resolve(DIRECTORY_NAME);

    Files.walkFileTree(pathToBeDeleted,
      new SimpleFileVisitor() {
        @Override
        public FileVisitResult postVisitDirectory(
          Path dir, IOException exc) throws IOException {
            Files.delete(dir);
            return FileVisitResult.CONTINUE;
        }

        @Override
        public FileVisitResult visitFile(
          Path file, BasicFileAttributes attrs)
          throws IOException {
            Files.delete(file);
            return FileVisitResult.CONTINUE;
        }
    });

    assertFalse("Directory still exists",
      Files.exists(pathToBeDeleted));
}

Die MethodeFiles.walkFileTree()durchläuft einen Dateibaum und gibt Ereignisse aus. Für diese Ereignisse müssen Rückrufe angegeben werden. In diesem Fall definieren wirSimpleFileVisitor, um die folgenden Aktionen für die generierten Ereignisse auszuführen:

  1. Eine Datei besuchen - löschen

  2. Ein Verzeichnis besuchen, bevor seine Einträge verarbeitet werden - nichts tun

  3. Besuchen Sie ein Verzeichnis nach der Verarbeitung seiner Einträge - löschen Sie das Verzeichnis, da alle Einträge in diesem Verzeichnis inzwischen verarbeitet (oder gelöscht) worden wären

  4. Datei kann nicht aufgerufen werden -IOException erneut auslösen, die den Fehler verursacht haben

Weitere Informationen zu NIO2-APIs zur Behandlung von Dateivorgängen finden Sie unterIntroduction to the Java NIO2 File API.

6. Verwenden vonNIO2 with Java 8

Stream API bietet seit Java 8 eine noch bessere Möglichkeit, ein Verzeichnis zu löschen:

@Test
public void whenDeletedWithFilesWalk_thenIsGone()
  throws IOException {
    Path pathToBeDeleted = TEMP_DIRECTORY.resolve(DIRECTORY_NAME);

    Files.walk(pathToBeDeleted)
      .sorted(Comparator.reverseOrder())
      .map(Path::toFile)
      .forEach(File::delete);

    assertFalse("Directory still exists",
      Files.exists(pathToBeDeleted));
}

Hier gibtFiles.walk()Stream vonPath zurück, die wir in umgekehrter Reihenfolge sortieren. Dadurch werden die Pfade, die den Inhalt von Verzeichnissen angeben, vor den Verzeichnissen selbst platziert. Danach ordnet esPathFile zu und löscht jedesFile.

7. Fazit

In diesem kurzen Lernprogramm haben wir verschiedene Möglichkeiten zum Löschen eines Verzeichnisses untersucht. Während wir sahen, wie man mithilfe von Rekursion löscht, haben wir uns auch einige Bibliotheken, NIO2-Nutzereignisse und Java 8 Path Stream mit einem funktionalen Programmierparadigma angesehen.

Alle Quellcodes und Testfälle für diesen Artikel sind inover on Github verfügbar.