2009-02-18 5 views
27

Angenommen, ich habe eine File f, die ein Verzeichnis darstellt, dann löscht f.delete() das Verzeichnis nur, wenn es leer ist. Ich habe einen couple von examples online gefunden, der File.listFiles() oder File.list() verwendet, um alle Dateien in dem Verzeichnis abzurufen, und rekursiv anschließend die Verzeichnisstruktur durchsucht und alle Dateien löscht. Da es jedoch möglich ist, unendlich rekursive Verzeichnisstrukturen zu erstellen (sowohl in Windows als auch in Linux (mit symbolischen Links)), ist es wahrscheinlich möglich, dass Programme, die in diesem Stil geschrieben sind, niemals enden.Löschen von nicht leeren Verzeichnissen in Java

Gibt es also einen besseren Weg, ein solches Programm zu schreiben, damit es nicht in diese Fallstricke gerät? Muss ich den Überblick behalten, wohin ich auch gefahren bin, und sicherstellen, dass ich nicht im Kreis herumlaufe oder gibt es einen schöneren Weg?

Update: Als Antwort auf einige der Antworten (Danke Jungs!) - Ich würde lieber den Code nicht folgen symbolische Links und blieb innerhalb des Verzeichnisses, das es löschen sollte. Kann ich das auf die Commons-IO-Implementierung anwenden, auch im Windows-Fall?

Antwort

32

Wenn Sie wirklich wollen, dass Ihre rekursive Verzeichnislöschung durch symbolische Links folgt, dann glaube ich nicht, dass es eine plattformunabhängige Vorgehensweise gibt, ohne alle Verzeichnisse im Auge zu behalten, die Sie durchlaufen haben.

Aber in fast jedem Fall kann ich daran denken, dass Sie nur die tatsächliche symbolische Verbindung löschen möchten, die auf das Verzeichnis verweist, anstatt rekursiv den symbolischen Link zu verfolgen.

Wenn dies das gewünschte Verhalten ist, können Sie die Methode FileUtils.deleteDirectory in Apache Commons IO verwenden.

3

File.getCanonicalPath() wird Ihnen den "echten" Namen der Datei sagen, einschließlich der aufgelösten Symlinks. Beim Scannen stößt man auf ein Verzeichnis, das man schon kennt (weil man sie in einem Map abgelegt hat).

+0

Ich hätte gedacht, dass eine rekursive Löschung ziemlich verlangsamen würde. Können Sie nicht eine File.getPath(). Equals (File.getCanonicalPath())? –

+0

Ich bin mir nicht sicher, wie viele gazillions von rekursiven Verzeichnissen Sie verarbeiten möchten, aber ein Map.put() und ein Map.contains() pro Verzeichnis werden Sie nicht verlangsamen. Der von dir vorgeschlagene Code würde dir nur sagen, dass irgendwo auf deinem Pfad symbolische Links stehen. Sie befinden sich möglicherweise über dem Verzeichnis, das Sie löschen möchten. – Bombe

+2

Ehrlich gesagt: Sorgen Sie sich darum, die Arbeit zuerst zu erledigen.Nur wenn es perfekt funktioniert und Sie können messen, dass es langsam ist (was auch immer das bedeutet), dann fangen Sie erst an, sich Gedanken über die Leistung zu machen. Vorzeitige Optimierung ist so hirnlos, dass es mir weh tut. Physisch. – Bombe

0

Wenn Sie wissen könnten, welche Dateien Symlinks sind, können Sie diese überspringen.

Es gibt leider keine "saubere" Möglichkeit, Symlinks in Java zu erkennen. Überprüfen Sie die reine Java-Problemumgehung this oder this one mit nativem Code.

7

Versuchen Sie Apache Commons IO für eine getestete Implementierung.

Allerdings glaube ich nicht, dass dies das Problem der unendlichen Rekursion behandelt.

+2

Blick auf die Quelle: http://svn.apache.org/viewvc/commons/proper/io/trunk/src/java/org/apache/commons/io/FileUtils.java?view=markup Sie werden die sehen deleteDirectory folgt nicht symbolischen Links. – elou

0

Zumindest unter MacOSX löscht das Löschen eines symbolischen Links zu einem Verzeichnis das Verzeichnis selbst nicht und kann daher gelöscht werden, auch wenn das Zielverzeichnis nicht leer ist.

Ich gehe davon aus, dass dies für die meisten POSIX-Betriebssysteme gilt. Und soweit ich weiß, sind Links unter Windows auch nur Dateien und können als solche aus einem Java-Programm gelöscht werden.