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();
    }
}

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
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!


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



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();
}

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


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.


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));

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();
}

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;
            }
        });
    }
}

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).


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;
        }
    });
}

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!


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();
        }
    }

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);
        }
    }

2

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


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();
    }
}

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() );
}
}


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);
    }
}

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.


0
private void deleteFileOrFolder(File file){
    try {
        for (File f : file.listFiles()) {
            f.delete();
            deleteFileOrFolder(f);
        }
    } catch (Exception e) {
        e.printStackTrace(System.err);
    }
}

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 :)


-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");

-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.


-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();
    }
}

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
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.