444 Stimmen

Verzeichnisse rekursiv löschen in Java

Gibt es eine Möglichkeit, in Java ganze Verzeichnisse rekursiv zu löschen?

Im Normalfall ist es möglich, ein leeres Verzeichnis zu löschen. Wenn es jedoch darum geht, ganze Verzeichnisse mit Inhalt zu löschen, ist das nicht mehr so einfach.

Wie kann man in Java ganze Verzeichnisse mit Inhalt löschen?

506voto

Steve K Punkte 19080

Sie sollten sich informieren über Apache's commons-io . Es hat eine FileUtils Klasse, die das tut, was Sie wollen.

FileUtils.deleteDirectory(new File("directory"));

199voto

erickson Punkte 256579

Mit Java 7 können wir endlich dies mit einer zuverlässigen Symlink-Erkennung tun. (Ich halte Apaches commons-io nicht für eine zuverlässig Symlink-Erkennung zu diesem Zeitpunkt, da es keine Links unter Windows behandelt, die mit mklink .)

Um der Geschichte willen, hier eine Antwort aus der Zeit vor Java 7, die folgt Symlinks.

void delete(File f) throws IOException {
  if (f.isDirectory()) {
    for (File c : f.listFiles())
      delete(c);
  }
  if (!f.delete())
    throw new FileNotFoundException("Failed to delete file: " + f);
}

170voto

In Java 7+ können Sie verwenden Files Klasse. Der Code ist sehr einfach:

Path directory = Paths.get("/tmp");
Files.walkFileTree(directory, 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;
   }
});

90voto

RoK Punkte 881

Einzeiler-Lösung (Java8) um alle Dateien und Verzeichnisse rekursiv zu löschen, einschließlich des Startverzeichnisses:

Files.walk(Paths.get("c:/dir_to_delete/"))
                .map(Path::toFile)
                .sorted((o1, o2) -> -o1.compareTo(o2))
                .forEach(File::delete);

Wir verwenden einen Komparator für die umgekehrte Reihenfolge, da File::delete sonst nicht in der Lage wäre, ein möglicherweise nicht leeres Verzeichnis zu löschen. Wenn Sie also Verzeichnisse beibehalten und nur Dateien löschen wollen, entfernen Sie einfach den Komparator in sorted() oder die Sortierung vollständig entfernen und einen Dateifilter hinzufügen:

Files.walk(Paths.get("c:/dir_to_delete/"))
                .filter(Files::isRegularFile)
                .map(Path::toFile)
                .forEach(File::delete);

68voto

Trevor Robinson Punkte 14524

Mit Java 7 wurde die Unterstützung für das Wandern von Verzeichnissen mit Symlink-Behandlung hinzugefügt:

import java.nio.file.*;

public static void removeRecursive(Path path) throws IOException
{
    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 visitFileFailed(Path file, IOException exc) throws IOException
        {
            // try to delete the file anyway, even if its attributes
            // could not be read, since delete-only access is
            // theoretically possible
            Files.delete(file);
            return FileVisitResult.CONTINUE;
        }

        @Override
        public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOException
        {
            if (exc == null)
            {
                Files.delete(dir);
                return FileVisitResult.CONTINUE;
            }
            else
            {
                // directory iteration failed; propagate exception
                throw exc;
            }
        }
    });
}

Ich verwende dies als Ausweichmöglichkeit von plattformspezifischen Methoden (in diesem ungetestet Code):

public static void removeDirectory(Path directory) throws IOException
{
    // does nothing if non-existent
    if (Files.exists(directory))
    {
        try
        {
            // prefer OS-dependent directory removal tool
            if (SystemUtils.IS_OS_WINDOWS)
                Processes.execute("%ComSpec%", "/C", "RD /S /Q \"" + directory + '"');
            else if (SystemUtils.IS_OS_UNIX)
                Processes.execute("/bin/rm", "-rf", directory.toString());
        }
        catch (ProcessExecutionException | InterruptedException e)
        {
            // fallback to internal implementation on error
        }

        if (Files.exists(directory))
            removeRecursive(directory);
    }
}

(SystemUtils ist von Apache Commons Lang . Processes ist privat, aber sein Verhalten sollte offensichtlich sein.)

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X