remove - java file delete not working
Java.nio: eliminar el directorio recursivo más conciso (5)
Actualmente estoy tratando de eliminar recursivamente un directorio ... Por extraño que parezca, el código más corto que pude encontrar es el siguiente constructo, que emplea una clase interna ad-hoc y en un patrón de visitante ...
Path rootPath = Paths.get("data/to-delete");
try {
Files.walkFileTree(rootPath, new SimpleFileVisitor<Path>() {
@Override
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
System.out.println("delete file: " + file.toString());
Files.delete(file);
return FileVisitResult.CONTINUE;
}
@Override
public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOException {
Files.delete(dir);
System.out.println("delete dir: " + dir.toString());
return FileVisitResult.CONTINUE;
}
});
} catch(IOException e){
e.printStackTrace();
}
Fuente: here
Esto se siente terriblemente torpe y detallado, dado que las nuevas API de nio
eliminan mucho desorden y repetitivo ...
¿Hay alguna forma más corta de lograr una eliminación de directorio forzada y recursiva?
Estoy buscando métodos Java 1.8 nativos puros, así que no vincules a bibliotecas externas ...
La siguiente solución no necesita la conversión de objetos de Ruta a Archivo:
Path rootPath = Paths.get("/data/to-delete");
final List<Path> pathsToDelete = Files.walk(rootPath).sorted(Comparator.reverseOrder()).collect(Collectors.toList());
for(Path path : pathsToDelete) {
Files.deleteIfExists(path);
}
Puedes combinar NIO 2 y la API de Stream.
Path rootPath = Paths.get("/data/to-delete");
// before you copy and paste the snippet
// - read the post till the end
// - read the javadoc to understand what the code will do
//
// a) to follow softlinks (removes the linked file too) use
// Files.walk(rootPath, FileVisitOption.FOLLOW_LINKS)
//
// b) to not follow softlinks (removes only the softlink) use
// the snippet below
Files.walk(rootPath)
.sorted(Comparator.reverseOrder())
.map(Path::toFile)
.peek(System.out::println)
.forEach(File::delete);
-
Files.walk
- devuelve todos los archivos / directorios debajo derootPath
incluyendo -
.sorted
: ordena la lista en orden inverso, por lo que el directorio viene después de los subdirectorios y archivos incluidos -
.map
-.map
laPath
alFile
-
.peek
- solo muestra qué entrada se procesa -
.forEach
: llama al método.delete()
en cada objetoFile
EDITAR
Aquí hay algunas figuras.
El directorio /data/to-delete
contenía el rt.jar
desempaquetado de jdk1.8.0_73 y una compilación reciente de activemq .
files: 36,427
dirs : 4,143
size : 514 MB
Tiempos en milisegundos
int. SSD ext. USB3
NIO + Stream API 1,126 11,943
FileVisitor 1,362 13,561
Ambas versiones fueron ejecutadas sin imprimir nombres de archivos. El factor más limitante es la unidad. No la implementación.
EDITAR
Alguna información adicional sobre la opción FileVisitOption.FOLLOW_LINKS
.
Asume la siguiente estructura de archivos y directorios
/data/dont-delete/bar
/data/to-delete/foo
/data/to-delete/dont-delete -> ../dont-delete
Utilizando
Files.walk(rootPath, FileVisitOption.FOLLOW_LINKS)
seguirá los enlaces simbólicos y el archivo /tmp/dont_delete/bar
también se eliminará.
Utilizando
Files.walk(rootPath)
no seguirá los enlaces simbólicos y el archivo /tmp/dont_delete/bar
no se eliminará.
NOTA: Nunca use el código como copiar y pegar sin entender lo que hace.
Si solo debes usar Java 7 con NIO
Path path = Paths.get("./target/logs");
Files.walkFileTree(path, new SimpleFileVisitor<Path>() {
@Override
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
Files.delete(file);
return FileVisitResult.CONTINUE;
}
@Override
public FileVisitResult postVisitDirectory(Path dir, IOException exc)
throws IOException {
Files.delete(dir);
return FileVisitResult.CONTINUE;
}
});
Si ya tiene Spring Core como parte de su proyecto, esta es una manera fácil de hacerlo:
FileSystemUtils.deleteRecursively(file);
Files.walk(pathToBeDeleted)
.sorted(Comparator.reverseOrder())
.map(Path::toFile)
.forEach(File::delete);
Fuente: http://www.baeldung.com/java-delete-directory (Uso de NIO2 con Java 8).
Además, probablemente sea un comentario no deseado, pero sería mucho más limpio y más legible utilizar una biblioteca. Con el código en una función compartida, no ocupará mucho espacio. Cada persona que mira su código debe validar que este código se elimine correctamente, y de ninguna manera es obvio.