Elimina una directory in modo ricorsivo in Java

1. Introduzione

In questo articolo, illustreremo come eliminare una directory in modo ricorsivo in semplice Java. Vedremo anche alcune alternative per l'eliminazione delle directory utilizzando librerie esterne.

2. Eliminazione ricorsiva di una directory

Java ha un'opzione per eliminare una directory. Tuttavia, ciò richiede che la directory sia vuota. Quindi, dobbiamo usare la ricorsione per eliminare una particolare directory non vuota:

  1. Ottieni tutti i contenuti della directory da eliminare
  2. Elimina tutti i figli che non sono una directory (esci dalla ricorsione)
  3. Per ogni sottodirectory della directory corrente, inizia con il passaggio 1 (passaggio ricorsivo)
  4. Elimina la directory

Implementiamo questo semplice algoritmo:

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

Questo metodo può essere testato utilizzando un semplice test case:

@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)); }

Il @Before il metodo della nostra classe di test crea un albero di directory con sottodirectory e file in pathToBeDeleted posizione e @After metodo pulisce directory, se necessario.

Successivamente, diamo un'occhiata a come possiamo ottenere l'eliminazione utilizzando due delle librerie più comunemente utilizzate: commons-io di Apache e spring-core di Spring Framework . Entrambe queste librerie ci consentono di eliminare le directory utilizzando solo una singola riga di codice.

3. Utilizzo di FileUtils da commons-io

Innanzitutto, dobbiamo aggiungere la dipendenza commons-io al progetto Maven:

 commons-io commons-io 2.5 

L'ultima versione della dipendenza può essere trovata qui.

Ora, possiamo usare FileUtils per eseguire qualsiasi operazione basata su file inclusa deleteDirectory () con una sola istruzione:

FileUtils.deleteDirectory(file);

4. Utilizzo di FileSystemUtils da Spring

In alternativa, possiamo aggiungere la dipendenza s pring-core al progetto Maven:

 org.springframework spring-core 4.3.10.RELEASE 

L'ultima versione della dipendenza può essere trovata qui.

Possiamo usare il metodo deleteRecursively () in FileSystemUtils per eseguire l'eliminazione:

boolean result = FileSystemUtils.deleteRecursively(file);

Le versioni recenti di Java offrono modi più nuovi per eseguire tali operazioni di I / O descritte nelle sezioni seguenti.

5. Utilizzo di NIO2 con Java 7

Java 7 ha introdotto un modo completamente nuovo di eseguire operazioni sui file utilizzando File . Ci consente di attraversare un albero di directory e utilizzare i callback per le azioni da eseguire.

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)); }

Il metodo Files.walkFileTree () attraversa un albero di file ed emette eventi. Dobbiamo specificare i callback per questi eventi. Quindi, in questo caso, definiremo SimpleFileVisitor per eseguire le seguenti azioni per gli eventi generati:

  1. Visitare un file: eliminarlo
  2. Visitare una directory prima di elaborare le sue voci: non fare nulla
  3. Visitare una directory dopo aver elaborato le sue voci: eliminare la directory, poiché tutte le voci all'interno di questa directory sarebbero state elaborate (o eliminate) a questo punto
  4. Impossibile visitare un file: lanciare nuovamente IOException che ha causato l'errore

Fare riferimento a Introduzione all'API file Java NIO2 per maggiori dettagli sulle API NIO2 sulla gestione delle operazioni sui file.

6. Utilizzo di NIO2 con Java 8

A partire da Java 8, Stream API offre un modo ancora migliore per eliminare una directory:

@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)); }

Qui, Files.walk () restituisce un flusso di percorso che ordiniamo in ordine inverso. In questo modo i percorsi che denotano il contenuto delle directory prima delle directory stesse. Successivamente mappa il percorso al file ed elimina ogni file.

7. Conclusione

In questo breve tutorial, abbiamo esplorato diversi modi per eliminare una directory. Mentre abbiamo visto come utilizzare la ricorsione per eliminare, abbiamo anche esaminato alcune librerie, eventi che sfruttano NIO2 e Java 8 Path Stream che impiega un paradigma di programmazione funzionale.

Tutto il codice sorgente e gli scenari di test per questo articolo sono disponibili su GitHub.