Jak usunąć folder z plikami za pomocą języka Java

104

Chcę utworzyć i usunąć katalog za pomocą Java, ale to nie działa.

File index = new File("/home/Work/Indexer1");
if (!index.exists()) {
    index.mkdir();
} else {
    index.delete();
    if (!index.exists()) {
        index.mkdir();
    }
}
Pan G.
źródło
3
Co się stało, kiedy próbowałeś?
Abimaran Kugathasan
Jakie jest pytanie?
Aniket Thakur
1
plik indeksu nie jest usuwany.
Pan G
1
Zobacz Jak usunąć katalog w Javie
Aniket Thakur
1
Niestety, @AniketThakur, takie podejście będzie podążać za dowiązaniami symbolicznymi i usuwać pliki i katalogi, które mogły nie być zamierzone.
Hank Schultz

Odpowiedzi:

99

Java nie może usunąć folderów zawierających dane. Musisz usunąć wszystkie pliki przed usunięciem folderu.

Użyj czegoś takiego:

String[]entries = index.list();
for(String s: entries){
    File currentFile = new File(index.getPath(),s);
    currentFile.delete();
}

Wtedy powinieneś być w stanie usunąć folder za pomocą index.delete() Untested!

Cemron
źródło
37
Nie spowoduje to usunięcia niepustych podkatalogów.
Francesco Menzani
13
musisz napisać metodę rekurencyjną lub użyć, FileUtils.deleteDirectoryjak powiedział @Francesco Menzani.
EN20
4
Bądź bardzo ostrożny. Jeśli indeks jest symbolicznym dowiązaniem do innego katalogu, skończysz usuwanie zawartości innego katalogu. Niestety, nie znalazłem jeszcze dobrego sposobu wykrywania dowiązań symbolicznych w systemie Windows w Javie 6, chociaż Java 7 udostępnia Files.isSymbolicLink ().
Hank Schultz
1
Rozwiązanie: zawiń ten fragment kodu w plik if (!index.delete()) {...}. Następnie, jeśli indeks jest dowiązaniem symbolicznym, jest usuwany niezależnie od tego, czy wygląda na to, że ma zawartość.
Hank Schultz
Spowoduje to zgłoszenie wyjątku NullPointerException, jeśli wystąpi wyjątek we / wy podczas odczytu katalogu. Kod powinien sprawdzać, czy entriesjest pusty.
mernst
178

Tylko jeden wiersz.

import org.apache.commons.io.FileUtils;

FileUtils.deleteDirectory(new File(destination));

Dokumentacja tutaj

Barry Knapp
źródło
13
yyy ... nie. Jest to jednowierszowy z zewnętrzną zależnością, o czym należy pamiętać. Jedyny przypadek, w którym korzystasz z takiej zewnętrznej zależności, jest tak prosty, gdy wykonujesz osobisty projekt domowy lub Twoja firma naprawdę nie dba o możliwość pozwu.
Searchengine 27
11
@earchchengine27, ale wygląda na to, że biblioteka znajduje się pod Apache Commons, więc ryzyko pozwu jest znikome . whitesourcesoftware.com/whitesource-blog/… .
simtim
1
@simtim całkowicie nie rozumiesz. Firma nigdy nie zezwoli na korzystanie z biblioteki bez zespołu prawników, którzy najpierw zapoznają się z warunkami użytkowania i umowami użytkownika końcowego oraz innymi dokumentami prawnymi związanymi z biblioteką. Ktoś musi tym prawnikom zapłacić ... czasami nikt nie chce, co oznacza, że ​​deweloper nie może z tego skorzystać. Im większa firma, dla której pracujesz, tym więcej biurokracji musisz przejść.
Searchengine 27
19
@earchchengine27 nie, całkowicie nie rozumiesz. Firma, która potrzebuje armii prawników, aby korzystać z apache commons, to absolutna patologia i nic w świecie IT. Nigdy nie słyszałem, żeby ktoś miał takie problemy, a jeśli masz takie problemy, najprawdopodobniej masz zablokowany dostęp do SO, więc odpowiedź i tak nie byłaby dla ciebie dostępna.
9ilsdx 9rvj 0lo
94

To działa i chociaż pomijanie testu katalogu wydaje się nieefektywne, tak nie jest: test jest wykonywany od razu w listFiles().

void deleteDir(File file) {
    File[] contents = file.listFiles();
    if (contents != null) {
        for (File f : contents) {
            deleteDir(f);
        }
    }
    file.delete();
}

Zaktualizuj, aby uniknąć następujących dowiązań symbolicznych:

void deleteDir(File file) {
    File[] contents = file.listFiles();
    if (contents != null) {
        for (File f : contents) {
            if (! Files.isSymbolicLink(f.toPath())) {
                deleteDir(f);
            }
        }
    }
    file.delete();
}
Jeff Learman
źródło
2
Jak się okazuje, jest w tym błąd. Jeśli inny proces usunie pliki podczas pętli, może to spowodować wyjątek, który powinien zostać przechwycony i zignorowany.
Jeff Learman,
2
@ 9ilsdx9rvj0lo Zamiast być wrednym, być może mógłbyś wprowadzić edycję obsługującą dowiązania symboliczne. OP nie wspomniał w swoim poście o symbolicznych linkach. Po prostu tworzenie i usuwanie katalogu. Proszę również wymienić „wiele rzeczy, których brakuje”. Pomóż nam.
Perry Tew,
@PerryTew Nie jestem złośliwy. Zwracam tylko uwagę, że całkowicie nie zgadzam się z twoim komentarzem, że odpowiedź jest lepsza, ponieważ nie są używane żadne biblioteki zewnętrzne. Nie jest. Jest dobry powód, dla którego ludzie używają apache commons: nie musisz samodzielnie programować żadnej rzeczy. Linki symboliczne to tylko przykład rzeczy, za którymi będziesz tęsknić, pisząc wszystko od zera.
9ilsdx 9rvj 0lo
2
Nie chodzi o lepsze / gorsze, ale o plusy i minusy. Brak opierania się na zewnętrznych bibliotekach jest czasami znaczącą korzyścią. Oczywiście korzystanie ze sprawdzonego oprogramowania ma wiele zalet. Wyważenie problemów należy do programisty. Jeśli istnieją błędy inne niż te dwa już wspomniane, z pewnością chcielibyśmy o nich wiedzieć.
Jeff Learman
31

Wolę to rozwiązanie w java 8:

  Files.walk(pathToBeDeleted)
    .sorted(Comparator.reverseOrder())
    .map(Path::toFile)
    .forEach(File::delete);

Z tej witryny: http://www.baeldung.com/java-delete-directory

nirmal
źródło
2
Zauważ, że może to mieć problemy ze skalowalnością, ponieważ tworzy pełną listę, tworzy posortowaną kopię, a następnie iteruje posortowaną kopię. W dawnych złych czasach, kiedy pamięć nie była niewyczerpana, byłby to bardzo zły pomysł. Jest zwięzły, ale kosztem przestrzeni (O (N) vs O (1)) i wydajności (O (N log N) vs O (N)). W większości przypadków nie miałoby to znaczenia.
Jeff Learman
Powinienem był powiedzieć „przestrzeń O (N) vs O (głębokość)” powyżej, gdzie głębokość jest głębokością drzewa katalogów (porównując to rozwiązanie z rozwiązaniami rekurencyjnymi).
Jeff Learman
1
to jest eleganckie, działa i nie opiera się na zewnętrznych bibliotekach. uwielbiałem to
Leo
Czy to nie ma problemu z wyciekami uchwytów plików? Ten przykład nie zamyka strumienia zwróconego przez Files.walk(), co jest wyraźnie wskazane w dokumentacji interfejsu API. Wiem, że jeśli nie zamkniesz strumienia zwróconego Files.list()na przykład przez, możesz zabraknąć uchwytów i program się zawiesi. Zobacz np. Stackoverflow.com/q/36990053/421049 i stackoverflow.com/q/26997240/421049 .
Garret Wilson
23

Korzystając z Apache Commons-IO, jest to jeden wiersz:

import org.apache.commons.io.FileUtils;

FileUtils.forceDelete(new File(destination));

Jest to (nieco) bardziej wydajne niż FileUtils.deleteDirectory.

JRA_TLL
źródło
grupa: 'commons-io', nazwa: 'commons-io', wersja: '2. +' - przydatne
mike gryzoń
10

Jak wspomniano, Java nie może usunąć folderu zawierającego pliki, dlatego najpierw usuń pliki, a następnie folder.

Oto prosty przykład, jak to zrobić:

import org.apache.commons.io.FileUtils;



// First, remove files from into the folder 
FileUtils.cleanDirectory(folder/path);

// Then, remove the folder
FileUtils.deleteDirectory(folder/path);

Lub:

FileUtils.forceDelete(new File(destination));
Gavriel Cohen
źródło
9

Moja podstawowa wersja rekurencyjna, działająca ze starszymi wersjami JDK:

public static void deleteFile(File element) {
    if (element.isDirectory()) {
        for (File sub : element.listFiles()) {
            deleteFile(sub);
        }
    }
    element.delete();
}
Pierre Lemée
źródło
2
Spowoduje to zgłoszenie wyjątku NullPointerException, jeśli wystąpi wyjątek we / wy podczas odczytu katalogu. Kod powinien sprawdzać, czy listFiles()zwraca null, zamiast wywoływać isDirectory().
mernst
9

To najlepsze rozwiązanie dla Java 7+:

public static void deleteDirectory(String directoryFilePath) throws IOException
{
    Path directory = Paths.get(directoryFilePath);

    if (Files.exists(directory))
    {
        Files.walkFileTree(directory, new SimpleFileVisitor<Path>()
        {
            @Override
            public FileVisitResult visitFile(Path path, BasicFileAttributes basicFileAttributes) throws IOException
            {
                Files.delete(path);
                return FileVisitResult.CONTINUE;
            }

            @Override
            public FileVisitResult postVisitDirectory(Path directory, IOException ioException) throws IOException
            {
                Files.delete(directory);
                return FileVisitResult.CONTINUE;
            }
        });
    }
}
BullyWiiPlaza
źródło
6

Na ratunek guawa 21+. Używaj tylko wtedy, gdy nie ma dowiązań symbolicznych wskazujących na katalog do usunięcia.

com.google.common.io.MoreFiles.deleteRecursively(
      file.toPath(),
      RecursiveDeleteOption.ALLOW_INSECURE
) ;

(To pytanie jest dobrze zindeksowane przez Google, więc inne osoby używające guawy mogą być szczęśliwe, gdy znajdą tę odpowiedź, nawet jeśli jest ona zbędna w przypadku innych odpowiedzi w innych miejscach).

Laurent Caillette
źródło
4

Najbardziej podoba mi się to rozwiązanie. Nie korzysta z biblioteki innej firmy, zamiast tego używa NIO2 Java 7.

/**
 * Deletes Folder with all of its content
 *
 * @param folder path to folder which should be deleted
 */
public static void deleteFolderAndItsContent(final Path folder) throws IOException {
    Files.walkFileTree(folder, 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 {
            if (exc != null) {
                throw exc;
            }
            Files.delete(dir);
            return FileVisitResult.CONTINUE;
        }
    });
}
Javo
źródło
3

Jeszcze jeden wybór to użycie org.springframework.util.FileSystemUtilsodpowiedniej metody Springa, która rekurencyjnie usunie całą zawartość katalogu.

File directoryToDelete = new File(<your_directory_path_to_delete>);
FileSystemUtils.deleteRecursively(directoryToDelete);

To wystarczy!

dZ.
źródło
2

W tym

index.delete();

            if (!index.exists())
               {
                   index.mkdir();
               }

dzwonisz

 if (!index.exists())
                   {
                       index.mkdir();
                   }

po

index.delete();

Oznacza to, że tworzysz plik ponownie po usunięciu File.delete () zwraca wartość logiczną, więc jeśli chcesz sprawdzić, zrób, System.out.println(index.delete());jeśli otrzymasz, trueoznacza to, że plik został usunięty

File index = new File("/home/Work/Indexer1");
    if (!index.exists())
       {
             index.mkdir();
       }
    else{
            System.out.println(index.delete());//If you get true then file is deleted




            if (!index.exists())
               {
                   index.mkdir();// here you are creating again after deleting the file
               }




        }

z komentarzy podanych poniżej, zaktualizowana odpowiedź jest taka

File f=new File("full_path");//full path like c:/home/ri
    if(f.exists())
    {
        f.delete();
    }
    else
    {
        try {
            //f.createNewFile();//this will create a file
            f.mkdir();//this create a folder
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
SpringLearner
źródło
2

Jeśli masz podfoldery, napotkasz problemy z odpowiedziami Cemron. więc powinieneś stworzyć metodę, która działa tak:

private void deleteTempFile(File tempFile) {
        try
        {
            if(tempFile.isDirectory()){
               File[] entries = tempFile.listFiles();
               for(File currentFile: entries){
                   deleteTempFile(currentFile);
               }
               tempFile.delete();
            }else{
               tempFile.delete();
            }
        getLogger().info("DELETED Temporal File: " + tempFile.getPath());
        }
        catch(Throwable t)
        {
            getLogger().error("Could not DELETE file: " + tempFile.getPath(), t);
        }
    }
Panthro
źródło
2

Możesz użyć FileUtils.deleteDirectory . JAVA nie może usunąć niepustych folderów za pomocą File.delete () .

Issam Ressani
źródło
1

Directry nie może po prostu usunąć, jeśli zawiera pliki, więc może być konieczne usunięcie najpierw plików, a następnie katalogu

public class DeleteFileFolder {

public DeleteFileFolder(String path) {

    File file = new File(path);
    if(file.exists())
    {
        do{
            delete(file);
        }while(file.exists());
    }else
    {
        System.out.println("File or Folder not found : "+path);
    }

}
private void delete(File file)
{
    if(file.isDirectory())
    {
        String fileList[] = file.list();
        if(fileList.length == 0)
        {
            System.out.println("Deleting Directory : "+file.getPath());
            file.delete();
        }else
        {
            int size = fileList.length;
            for(int i = 0 ; i < size ; i++)
            {
                String fileName = fileList[i];
                System.out.println("File path : "+file.getPath()+" and name :"+fileName);
                String fullPath = file.getPath()+"/"+fileName;
                File fileOrFolder = new File(fullPath);
                System.out.println("Full Path :"+fileOrFolder.getPath());
                delete(fileOrFolder);
            }
        }
    }else
    {
        System.out.println("Deleting file : "+file.getPath());
        file.delete();
    }
}
Indranil.Bharambe
źródło
1

Możesz wykonać wywołanie rekurencyjne, jeśli istnieją podkatalogi

import java.io.File;

class DeleteDir {
public static void main(String args[]) {
deleteDirectory(new File(args[0]));
}

static public boolean deleteDirectory(File path) {
if( path.exists() ) {
  File[] files = path.listFiles();
  for(int i=0; i<files.length; i++) {
     if(files[i].isDirectory()) {
       deleteDirectory(files[i]);
     }
     else {
       files[i].delete();
     }
  }
}
return( path.delete() );
}
}
prem30488
źródło
1

możemy użyć spring-corezależności;

boolean result = FileSystemUtils.deleteRecursively(file);
Kanagavelu Sugumar
źródło
1

Większość odpowiedzi (nawet ostatnich) odnoszących się do klas JDK polega na File.delete()tym, że jest to wadliwy interfejs API, ponieważ operacja może zakończyć się cichym niepowodzeniem.
Dokumentacja java.io.File.delete()metody stwierdza:

Zauważ, że java.nio.file.Filesklasa definiuje deletemetodę zgłaszania, IOExceptiongdy nie można usunąć pliku. Jest to przydatne przy zgłaszaniu błędów i diagnozowaniu, dlaczego pliku nie można usunąć.

Jako zamiennik powinieneś preferować, Files.delete(Path p) że wyrzuca komunikat IOExceptionz komunikatem o błędzie.

Rzeczywisty kod można napisać na przykład:

Path index = Paths.get("/home/Work/Indexer1");

if (!Files.exists(index)) {
    index = Files.createDirectories(index);
} else {

    Files.walk(index)
         .sorted(Comparator.reverseOrder())  // as the file tree is traversed depth-first and that deleted dirs have to be empty  
         .forEach(t -> {
             try {
                 Files.delete(t);
             } catch (IOException e) {
                 // LOG the exception and potentially stop the processing

             }
         });
    if (!Files.exists(index)) {
        index = Files.createDirectories(index);
    }
}
davidxxx
źródło
0

możesz spróbować w następujący sposób

  File dir = new File("path");
   if (dir.isDirectory())
   {
         dir.delete();
   }

Jeśli w folderze znajdują się podfoldery, może być konieczne ich rekurencyjne usuwanie.

Ruchira Gayan Ranaweera
źródło
0
private void deleteFileOrFolder(File file){
    try {
        for (File f : file.listFiles()) {
            f.delete();
            deleteFileOrFolder(f);
        }
    } catch (Exception e) {
        e.printStackTrace(System.err);
    }
}
Marcelo Lopes
źródło
0
        import org.apache.commons.io.FileUtils;

        List<String> directory =  new ArrayList(); 
        directory.add("test-output"); 
        directory.add("Reports/executions"); 
        directory.add("Reports/index.html"); 
        directory.add("Reports/report.properties"); 
        for(int count = 0 ; count < directory.size() ; count ++)
        {
        String destination = directory.get(count);
        deleteDirectory(destination);
        }





      public void deleteDirectory(String path) {

        File file  = new File(path);
        if(file.isDirectory()){
             System.out.println("Deleting Directory :" + path);
            try {
                FileUtils.deleteDirectory(new File(path)); //deletes the whole folder
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
        else {
        System.out.println("Deleting File :" + path);
            //it is a simple file. Proceed for deletion
            file.delete();
        }

    }

Działa jak marzenie . Zarówno w przypadku folderów, jak i plików. Salam :)

Mushtaque Ahmed
źródło
-1

Usuń go z innej części

File index = new File("/home/Work/Indexer1");
if (!index.exists())
{
     index.mkdir();
     System.out.println("Dir Not present. Creating new one!");
}
index.delete();
System.out.println("File deleted successfully");
Aniket Thakur
źródło
-1

Niektóre z tych odpowiedzi wydają się niepotrzebnie długie:

if (directory.exists()) {
    for (File file : directory.listFiles()) {
        file.delete();
    }
    directory.delete();
}

Działa również dla podkatalogów.

Adam Short
źródło
-3

Możesz użyć tej funkcji

public void delete()    
{   
    File f = new File("E://implementation1/");
    File[] files = f.listFiles();
    for (File file : files) {
        file.delete();
    }
}
Piyush Rumao
źródło
Działa dobrze z katalogiem zawierającym wszystkie zamknięte pliki. Ale kiedy próbowałem na katalogu z otwartymi plikami, to nie działa. Czy możesz mi pomóc znaleźć sposób na usunięcie folderu pomimo otwartych plików
Piyush Rumao
2
Nie spowoduje to usunięcia niepustych podkatalogów.
Pang