Supprimer un répertoire de manière récursive en Java

1. Introduction

Dans cet article, nous allons illustrer comment supprimer un répertoire de manière récursive en Java brut. Nous examinerons également quelques alternatives pour supprimer des répertoires à l'aide de bibliothèques externes.

2. Suppression récursive d'un répertoire

Java a une option pour supprimer un répertoire. Cependant, cela nécessite que le répertoire soit vide. Donc, nous devons utiliser la récursivité pour supprimer un répertoire non vide particulier:

  1. Récupère tout le contenu du répertoire à supprimer
  2. Supprimer tous les enfants qui ne sont pas un répertoire (sortie de la récursivité)
  3. Pour chaque sous-répertoire du répertoire courant, commencez par l'étape 1 (étape récursive)
  4. Supprimer le répertoire

Implémentons cet algorithme simple:

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

Cette méthode peut être testée à l'aide d'un cas de test simple:

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

La @Before méthode de notre classe de test crée une arborescence de répertoires avec les sous - répertoires et fichiers à pathToBeDeleted emplacement et @After méthode nettoie le répertoire si nécessaire.

Ensuite, voyons comment nous pouvons réaliser la suppression à l'aide de deux des bibliothèques les plus couramment utilisées: commons-io d' Apache et spring-core de Spring Framework . Ces deux bibliothèques nous permettent de supprimer les répertoires en utilisant une seule ligne de code.

3. Utilisation de FileUtils depuis commons-io

Tout d'abord, nous devons ajouter la dépendance commons-io au projet Maven:

 commons-io commons-io 2.5 

La dernière version de la dépendance peut être trouvée ici.

Maintenant, nous pouvons utiliser FileUtils pour effectuer toutes les opérations basées sur des fichiers, y compris deleteDirectory () avec une seule instruction:

FileUtils.deleteDirectory(file);

4. Utilisation de FileSystemUtils de Spring

Alternativement, nous pouvons ajouter la dépendance s pring-core au projet Maven:

 org.springframework spring-core 4.3.10.RELEASE 

La dernière version de la dépendance peut être trouvée ici.

Nous pouvons utiliser la méthode deleteRecursively () dans FileSystemUtils pour effectuer la suppression:

boolean result = FileSystemUtils.deleteRecursively(file);

Les versions récentes de Java offrent de nouvelles méthodes pour effectuer ces opérations d'E / S décrites dans les sections suivantes.

5. Utilisation de NIO2 avec Java 7

Java 7 a introduit une toute nouvelle façon d'effectuer des opérations sur les fichiers à l' aide de Files . Cela nous permet de parcourir une arborescence de répertoires et d'utiliser des rappels pour les actions à effectuer.

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

La méthode Files.walkFileTree () parcourt une arborescence de fichiers et émet des événements. Nous devons spécifier des rappels pour ces événements. Donc, dans ce cas, nous allons définir SimpleFileVisitor pour prendre les actions suivantes pour les événements générés:

  1. Visiter un fichier - le supprimer
  2. Visiter un répertoire avant de traiter ses entrées - ne rien faire
  3. Visiter un répertoire après avoir traité ses entrées - supprimez le répertoire, car toutes les entrées de ce répertoire auraient été traitées (ou supprimées) maintenant
  4. Impossible de visiter un fichier - relancez IOException qui a causé l'échec

Veuillez consulter Introduction à l'API de fichier Java NIO2 pour plus de détails sur les API NIO2 sur la gestion des opérations sur les fichiers.

6. Utilisation de NIO2 avec Java 8

Depuis Java 8, l'API Stream offre un moyen encore meilleur de supprimer un répertoire:

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

Ici, Files.walk () renvoie un Stream of Path que nous trions dans l'ordre inverse. Cela place les chemins indiquant le contenu des répertoires avant les répertoires eux-mêmes. Ensuite, il mappe le chemin vers le fichier et supprime chaque fichier.

7. Conclusion

Dans ce rapide didacticiel, nous avons exploré différentes manières de supprimer un répertoire. Bien que nous ayons vu comment utiliser la récursivité pour supprimer, nous avons également examiné certaines bibliothèques, NIO2 tirant parti des événements et Java 8 Path Stream utilisant un paradigme de programmation fonctionnel.

Tous le code source et les scénarios de test de cet article sont disponibles à l'adresse over sur GitHub.