Czy istnieje sposób, aby rekurencyjnie usuwać całe katalogi w Javie?
W normalnym przypadku możliwe jest usunięcie pustego katalogu. Jednak jeśli chodzi o usuwanie całych katalogów z zawartością, nie jest to już takie proste.
Jak usunąć całe katalogi z zawartością w Javie?
java
file-io
filesystems
delete-directory
pawelokowy
źródło
źródło
Odpowiedzi:
Powinieneś sprawdzić commons-io Apache . Ma klasę FileUtils , która zrobi to, co chcesz.
źródło
W Javie 7 możemy wreszcie to zrobić dzięki niezawodnemu wykrywaniu dowiązań symbolicznych. (Nie uważam, że commons-io firmy Apache ma teraz niezawodne wykrywanie dowiązań symbolicznych, ponieważ nie obsługuje linków w systemie Windows utworzonych za pomocą
mklink
.)Ze względu na historię, oto odpowiedź wcześniejsza niż Java 7, która następuje po dowiązaniach symbolicznych.
źródło
foo
z łączemfoo/link
takim, żelink->/
wywołaniedelete(new File(foo))
skasuje tyle systemu plików, ile użytkownik może !!W Javie 7+ możesz używać
Files
klasy. Kod jest bardzo prosty:źródło
super.postVisitDirectory(dir, exc);
swojąpostVisitDirectory
metodę, aby wysadzić w powietrze, jeśli spacer nie może wyświetlić katalogu.Jednoliniowe rozwiązanie (Java8) do rekurencyjnego usuwania wszystkich plików i katalogów, w tym katalogu startowego:
Używamy komparatora w odwrotnej kolejności, w przeciwnym razie File :: delete nie będzie w stanie usunąć potencjalnie niepustego katalogu. Tak więc, jeśli chcesz zachować katalogi i usuwać tylko pliki, po prostu usuń komparator w sorted () lub całkowicie usuń sortowanie i dodaj filtr plików:
źródło
.sorted(Comparator.reverseOrder())
sugestiaComparator::reverseOrder
ma nie działać. Zobacz: stackoverflow.com/questions/43036611/….sorted((f1, f2) -> f2.compareTo(f1))
:, porównującf2
zf1
zamiastf1
zf2
.Java 7 dodała obsługę katalogów kroczących z obsługą dowiązań symbolicznych:
Używam tego jako rezerwy metod specyficznych dla platformy (w tym nieprzetestowanym kodzie):
(SystemUtils pochodzi z Apache Commons Lang . Procesy są prywatne, ale ich zachowanie powinno być oczywiste.)
źródło
Właśnie zobaczyłem, że moje rozwiązanie jest mniej więcej takie samo jak rozwiązanie Ericksona, po prostu spakowane jako metoda statyczna. Upuść to gdzieś, jest znacznie lżejsze niż instalacja całego Apache Commons dla czegoś, co (jak widać) jest dość proste.
źródło
Rozwiązanie ze stosem i bez metod rekurencyjnych:
źródło
list*
metody klasyjava.io.File
. Z Javadocs: „Zwraca null, jeśli ta abstrakcyjna nazwa ścieżki nie oznacza katalogu, lub jeśli wystąpi błąd we / wy”. Więc:if (currList.length > 0) {
staje sięif (null != currList && currList.length > 0) {
Jeśli masz Spring, możesz użyć FileSystemUtils.deleteRecursively :
źródło
Guawa był
Files.deleteRecursively(File)
wspierany aż Guava 9 .Od Guawy 10 :
Dlatego w Guava 11 nie ma takiej metody .
źródło
Lub jeśli chcesz obsłużyć
IOException
:źródło
Files.walk(path).iterator().toSeq.reverse.foreach(Files.delete)
walk
metoda już gwarantuje przejście przez pierwszą głębokość.Collections.reverseOrder()
aby kod mógłfor (Path p : Files.walk(directoryToDelete).sorted(reverseOrder()).toArray(Path[]::new))
zakładać, że został zaimportowany statycznie.Comparator.reverseOrder
?Files.walk(dir) .sorted(Comparator.reverseOrder()) .toArray(Path[]::new))
źródło
źródło
f.delete()
poniżejdeleteDirectory(f)
wygeneruje wyjątek NoSuchFileException, ponieważdeleteDirectory(f)
ten plik został już usunięty. Każdy katalog stanie się ścieżką po przekazaniudeleteDirectory(f)
i usunięciu przezpath.delete()
. Dlatego nie potrzebujemyf.delete()
wif f.isDerectory
sekcji. Więc po prostu usuńf.delete();
w deleteDirectory (f) i to zadziała.Dwa sposoby na niepowodzenie z dowiązaniami symbolicznymi i powyższym kodem ... i nie znam rozwiązania.
Sposób nr 1
Uruchom to, aby utworzyć test:
Tutaj widzisz swój plik testowy i katalog testowy:
Następnie uruchom commons-io deleteDirectory (). Awaria oznacza, że plik nie został znaleziony. Nie jestem pewien, co robią tutaj inne przykłady. Polecenie Linux rm po prostu usunę łącze, a także rm -r w katalogu.
Sposób nr 2
Uruchom to, aby utworzyć test:
Tutaj widzisz swój plik testowy i katalog testowy:
Następnie uruchom commons-io deleteDirectory () lub przykładowy kod opublikowany przez osoby. Usuwa nie tylko katalog, ale także plik testowy znajdujący się poza katalogiem, który jest usuwany. (Ujawnia katalog domyślnie i usuwa zawartość). rm -r usunie tylko link. Musisz użyć czegoś takiego: usuń dereferencyjne pliki: "find -L dirtodelete -type f -exec rm {} \;".
źródło
Możesz użyć:
org.apache.commons.io.FileUtils.deleteQuietly(destFile);
Usuwa plik, nigdy nie zgłaszając wyjątku. Jeśli plik jest katalogiem, usuń go i wszystkie podkatalogi. Różnica między File.delete () a tą metodą jest taka: Katalog do usunięcia nie musi być pusty. Nie można zgłaszać wyjątków, gdy pliku lub katalogu nie można usunąć.
źródło
Optymalne rozwiązanie, które obsługuje wyjątek spójnie z podejściem, że wyjątek zgłoszony przez metodę powinien zawsze opisywać to, czego ta metoda próbowała (i nie udało się):
źródło
W starszych projektach muszę utworzyć natywny kod Java. Tworzę ten kod podobny do kodu Paulitex. Zobaczyć, że:
I test jednostkowy:
źródło
Poniższy kod rekurencyjnie usuwa całą zawartość w danym folderze.
źródło
Oto główna metoda z odkrytymi kośćmi, która akceptuje argument wiersza poleceń, może być konieczne dołączenie własnego sprawdzania błędów lub ukształtowanie go według własnego uznania.
Mam nadzieję że to pomogło!
źródło
Być może rozwiązaniem tego problemu może być ponowne zaimplementowanie metody usuwania klasy File przy użyciu kodu z odpowiedzi Erickson:
źródło
Bez Commons IO i <Java SE 7
źródło
Podczas gdy pliki można łatwo usunąć za pomocą file.delete (), katalogi muszą być puste, aby je usunąć. Użyj rekurencji, aby to zrobić z łatwością. Na przykład:
źródło
Kodowałem tę procedurę, która ma 3 kryteria bezpieczeństwa dla bezpieczniejszego użytkowania.
źródło
Załóżmy przykład:
Aby uzyskać więcej informacji, zapoznaj się z poniższymi zasobami
Usuń katalog
źródło
rm -rf
był znacznie bardziej wydajny niżFileUtils.deleteDirectory
.Po szeroko zakrojonych testach porównawczych stwierdziliśmy, że używanie
rm -rf
było wielokrotnie szybsze niż używanieFileUtils.deleteDirectory
.Oczywiście, jeśli masz mały lub prosty katalog, nie będzie to miało znaczenia, ale w naszym przypadku mieliśmy wiele gigabajtów i głęboko zagnieżdżone podkatalogi, w których zajęłoby to ponad 10 minut
FileUtils.deleteDirectory
i tylko 1 minutarm -rf
.Oto nasza przybliżona implementacja Java, aby to zrobić:
Warto spróbować, jeśli masz do czynienia z dużymi lub złożonymi katalogami.
źródło
Guava zapewnia jedno-liniowy:
MoreFiles.deleteRecursively()
.W przeciwieństwie do wielu udostępnionych przykładów, uwzględnia linki symboliczne i nie usuwa (domyślnie) plików poza podaną ścieżką.
źródło