Excluir um diretório recursivamente em Java
1. Introdução
Neste artigo, ilustraremos como excluir um diretório recursivamente em Java simples. Também veremos algumas alternativas para excluir diretórios usando bibliotecas externas.
2. Exclusão de um diretório recursivamente
Java tem uma opção para excluir um diretório. No entanto, isso requer que o diretório esteja vazio. Portanto, precisamos usar a recursão para excluir um diretório não vazio específico:
-
Obter todo o conteúdo do diretório a ser excluído
-
Exclua todos os filhos que não são um diretório (saia da recursão)
-
Para cada subdiretório do diretório atual, inicie com a etapa 1 (etapa recursiva)
-
Excluir o diretório
Vamos implementar este algoritmo simples:
boolean deleteDirectory(File directoryToBeDeleted) {
File[] allContents = directoryToBeDeleted.listFiles();
if (allContents != null) {
for (File file : allContents) {
deleteDirectory(file);
}
}
return directoryToBeDeleted.delete();
}
Este método pode ser testado usando um caso de teste direto:
@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));
}
O método@Before de nossa classe de teste cria uma árvore de diretórios com subdiretórios e arquivos na localizaçãopathToBeDeleted e o método@After limpa o diretório, se necessário.
A seguir, vamos dar uma olhada em como podemos conseguir a exclusão usando duas das bibliotecas mais comumente usadas -commons-io do Apache espring-core. do Spring Framework. Ambas as bibliotecas nos permitem excluir os diretórios usando apenas uma linha de código.
3. UsandoFileUtils decommons-io
Primeiro, precisamos adicionar a dependênciacommons-io ao projeto Maven:
commons-io
commons-io
2.5
A versão mais recente da dependência pode ser encontradahere.
Agora, podemos usarFileUtils para realizar qualquer operação baseada em arquivo, incluindodeleteDirectory() com apenas uma instrução:
FileUtils.deleteDirectory(file);
4. UsandoFileSystemUtils do Spring
Como alternativa, podemos adicionar a dependência spring-core ao projeto Maven:
org.springframework
spring-core
4.3.10.RELEASE
A última versão da dependência pode ser encontradahere.
Podemos usar o métododeleteRecursively() emFileSystemUtils para realizar a exclusão:
boolean result = FileSystemUtils.deleteRecursively(file);
Os releases recentes do Java oferecem maneiras mais recentes de executar essas operações de E / S descritas nas seções a seguir.
5. Usando NIO2 com Java 7
Java 7 introduziu uma maneira totalmente nova de realizar operações de arquivo usandoFiles. Ele nos permite percorrer uma árvore de diretórios e usar retornos de chamada para ações a serem executadas.
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));
}
O métodoFiles.walkFileTree() percorre uma árvore de arquivos e emite eventos. Precisamos especificar retornos de chamada para esses eventos. Portanto, neste caso, definiremosSimpleFileVisitor para realizar as seguintes ações para os eventos gerados:
-
Visitando um arquivo - exclua-o
-
Visitar um diretório antes de processar suas entradas - não faça nada
-
Visitar um diretório após processar suas entradas - exclua o diretório, pois todas as entradas nesse diretório já teriam sido processadas (ou excluídas) até agora
-
Incapaz de visitar um arquivo - relançarIOException que causou a falha
ConsulteIntroduction to the Java NIO2 File API para obter mais detalhes sobre APIs NIO2 sobre como lidar com operações de arquivo.
6. UsandoNIO2 with Java 8
Desde o Java 8, a Stream API oferece uma maneira ainda melhor de excluir um diretório:
@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));
}
Aqui,Files.walk() retorna umStream dePath que classificamos na ordem inversa. Isso coloca os caminhos que indicam o conteúdo dos diretórios antes dos próprios diretórios. Depois disso, mapeiaPath aFilee exclui cadaFile.
7. Conclusão
Neste tutorial rápido, exploramos diferentes maneiras de excluir um diretório. Enquanto vimos como usar a recursão para excluir, também vimos algumas bibliotecas, eventos de alavancagem da NIO2 e o Java 8 Path Stream empregando um paradigma de programação funcional.
Todo o código-fonte e casos de teste para este artigo estão disponíveisover on Github.