Come eliminare una cartella con file utilizzando Java


104

Voglio creare ed eliminare una directory utilizzando Java, ma non funziona.

File index = new File("/home/Work/Indexer1");
if (!index.exists()) {
    index.mkdir();
} else {
    index.delete();
    if (!index.exists()) {
        index.mkdir();
    }
}

3
Cosa è successo quando hai provato?
Abimaran Kugathasan

Qual'è la domanda?
Aniket Thakur

1
file indice non rimosso.
Signor G


1
Sfortunatamente, @AniketThakur, quell'approccio seguirà collegamenti simbolici ed eliminerà file e directory che potrebbero non essere stati previsti.
Hank Schultz

Risposte:


99

Java non è in grado di eliminare cartelle con dati al suo interno. È necessario eliminare tutti i file prima di eliminare la cartella.

Usa qualcosa come:

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

Quindi dovresti essere in grado di eliminare la cartella utilizzando index.delete() Untested!


37
Ciò non eliminerà le sottodirectory non vuote.
Francesco Menzani

13
devi scrivere un metodo ricorsivo o usarlo FileUtils.deleteDirectorycome ha detto @Francesco Menzani.
EN20

4
Essere molto attenti. Se index è un collegamento simbolico a un'altra directory, finirai per eliminare il contenuto dell'altra directory. Sfortunatamente, non ho ancora trovato un buon modo per rilevare i collegamenti simbolici su Windows in Java 6, sebbene Java 7 fornisca Files.isSymbolicLink ().
Hank Schultz

1
Soluzione: racchiudi questo pezzo di codice if (!index.delete()) {...}. Quindi, se l'indice è un collegamento simbolico, viene eliminato indipendentemente dal fatto che appaia che abbia dei contenuti.
Hank Schultz

Questo genererà un'eccezione NullPointerException se c'è un'eccezione I / O durante la lettura della directory. Il codice dovrebbe verificare se entriesè nullo.
mercoledì

178

Solo una battuta.

import org.apache.commons.io.FileUtils;

FileUtils.deleteDirectory(new File(destination));

Documentazione qui



13
um ... no. Questa è una battuta con una dipendenza esterna, che è una cosa importante da tenere a mente. L'unico momento in cui si utilizza una dipendenza esterna come questa è così semplice è quando stai facendo un progetto domestico personale, o alla tua azienda non interessa davvero la possibilità di essere citata in giudizio.
searchengine27

11
@ searchengine27 ma sembra che la libreria sia sotto Apache Commons, quindi il rischio di essere denunciato è trascurabile whitesourcesoftware.com/whitesource-blog/… .
simtim

1
@simtim ti manca completamente il punto. Un'azienda non approverà mai l'uso di una biblioteca senza prima che un team di avvocati si dilunghi sui termini di utilizzo e sugli accordi con l'utente finale e su qualsiasi altro documento legale associato alla biblioteca. Qualcuno deve pagare quegli avvocati ... a volte nessuno vuole, il che significa che lo sviluppatore non può usarlo. Più grande è l'azienda per cui lavori, più burocrazia dovrai affrontare.
searchengine27

19
@ searchengine27 no, ti manca completamente il punto. Un'azienda che ha bisogno di un esercito di avvocati per consentire di utilizzare apache commons è la patologia assoluta, e niente vicino alla norma nel mondo IT. Non ho mai sentito di nessuno che abbia tali problemi e se hai tali problemi molto probabilmente hai accesso a SO bloccato, quindi la risposta non sarebbe comunque accessibile.
9ilsdx 9rvj 0lo

94

Funziona, e anche se sembra inefficiente saltare il test della directory, non lo è: il test viene eseguito immediatamente in listFiles().

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

Aggiorna, per evitare i seguenti link simbolici:

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
A quanto pare, c'è un bug in questo. Se un altro processo elimina i file durante il ciclo, può causare un'eccezione che dovrebbe essere rilevata e ignorata.
Jeff Learman

2
@ 9ilsdx9rvj0lo Piuttosto che essere irriverente, forse potresti fornire una modifica per gestire i collegamenti simbolici. L'OP non ha detto nulla sui collegamenti simbolici nel suo post. Basta creare ed eliminare una directory. Elenca anche le "molte cose mancanti". Aiutaci.
Perry Tew

@PerryTew non sto facendo il sarcastico. Sto solo sottolineando che sono completamente in disaccordo con il tuo commento sul fatto che la risposta sia migliore perché non vengono utilizzate librerie esterne. Non è. C'è una buona ragione per cui le persone usano apache commons: non devi programmare nulla da solo. I collegamenti simbolici sono solo un esempio di cose che ti mancheranno di scrivere tutto da zero.
9ilsdx 9rvj 0lo

2
Non è una questione di meglio / peggio, ma pro e contro. Non fare affidamento su librerie esterne a volte è un vantaggio significativo. Ovviamente, c'è un vantaggio significativo nell'utilizzo di software collaudato. Spetta allo sviluppatore bilanciare i problemi. Se ci sono bug diversi dai due già citati, ci piacerebbe sicuramente conoscerli.
Jeff Learman

31

Preferisco questa soluzione su java 8:

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

Da questo sito: http://www.baeldung.com/java-delete-directory


2
Si noti che ciò potrebbe avere problemi di scalabilità poiché crea l'elenco completo, crea una copia ordinata e quindi esegue l'iterazione sulla copia ordinata. Ai vecchi tempi, quando la memoria non era inesauribile, questa sarebbe stata una pessima idea. È conciso ma ha un costo in termini di spazio (O (N) vs O (1)) ed efficienza (O (N log N) vs O (N)). Questo non avrebbe importanza nella maggior parte dei casi d'uso.
Jeff Learman

Avrei dovuto dire "spazio O (N) vs O (profondità)" sopra, dove la profondità è la profondità dell'albero delle directory (confrontando questa soluzione con quelle ricorsive).
Jeff Learman

1
questo è elegante, funziona e non si basa su librerie esterne. mi è piaciuto molto
Leone

Questo non ha il problema delle perdite di gestione dei file? Questo esempio non chiude il flusso restituito da Files.walk(), che è esplicitamente indicato nella documentazione dell'API. So che se non chiudi il flusso restituito da, Files.list()ad esempio, puoi esaurire gli handle e il programma andrà in crash. Vedi ad esempio stackoverflow.com/q/36990053/421049 e stackoverflow.com/q/26997240/421049 .
Garret Wilson


23

Utilizzando Apache Commons-IO, segue una riga:

import org.apache.commons.io.FileUtils;

FileUtils.forceDelete(new File(destination));

Questo è (leggermente) più performante di FileUtils.deleteDirectory.


gruppo: 'commons-io', nome: 'commons-io', versione: '2. +' - utile
mike rodent

10

Come accennato, Java non è in grado di eliminare una cartella che contiene file, quindi elimina prima i file e poi la cartella.

Ecco un semplice esempio per farlo:

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

O:

FileUtils.forceDelete(new File(destination));

9

La mia versione ricorsiva di base, che funziona con versioni precedenti di JDK:

public static void deleteFile(File element) {
    if (element.isDirectory()) {
        for (File sub : element.listFiles()) {
            deleteFile(sub);
        }
    }
    element.delete();
}

2
Questo genererà un'eccezione NullPointerException se c'è un'eccezione I / O durante la lettura della directory. Il codice dovrebbe verificare se listFiles()restituisce null, anziché chiamare isDirectory().
mercoledì

9

Questa è la migliore soluzione per 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

Guava 21+ in soccorso. Utilizzare solo se non ci sono collegamenti simbolici che puntano fuori dalla directory da eliminare.

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

(Questa domanda è ben indicizzata da Google, quindi altre persone che usano Guava potrebbero essere felici di trovare questa risposta, anche se è ridondante con altre risposte altrove.)


4

Mi piace di più questa soluzione. Non utilizza la libreria di terze parti, invece utilizza NIO2 di 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

Un'altra scelta è usare il org.springframework.util.FileSystemUtilsmetodo pertinente di Spring che cancellerà ricorsivamente tutto il contenuto della directory.

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

Questo farà il lavoro!


2

In questo

index.delete();

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

stai chiamando

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

dopo

index.delete();

Ciò significa che stai creando di nuovo il file dopo aver eliminato File.delete () restituisce un valore booleano Quindi se vuoi controllare, fallo System.out.println(index.delete());se ottieni, truesignifica che il file è stato cancellato

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
               }




        }

dai commenti riportati di seguito, la risposta aggiornata è così

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

Se hai sottocartelle, troverai problemi con le risposte Cemron. quindi dovresti creare un metodo che funzioni in questo modo:

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

È possibile utilizzare FileUtils.deleteDirectory . JAVA non può eliminare le cartelle non vuote con File.delete () .


1

directry non può semplicemente eliminare se ha i file, quindi potrebbe essere necessario eliminare prima i file all'interno e poi la directory

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

È possibile effettuare chiamate ricorsive se esistono sottodirectory

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

possiamo usare la spring-coredipendenza;

boolean result = FileSystemUtils.deleteRecursively(file);

1

La maggior parte delle risposte (anche recenti) che fanno riferimento a classi JDK si basano su, File.delete()ma questa è un'API difettosa in quanto l'operazione potrebbe non riuscire silenziosamente.
La java.io.File.delete()documentazione del metodo afferma:

Si noti che la java.nio.file.Filesclasse definisce il deletemetodo per lanciare un IOExceptionquando un file non può essere cancellato. Ciò è utile per la segnalazione degli errori e per diagnosticare il motivo per cui un file non può essere eliminato.

In sostituzione, dovresti preferire Files.delete(Path p) che genera un IOExceptionmessaggio di errore.

Il codice effettivo potrebbe essere scritto come:

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

puoi provare come segue

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

Se sono presenti sottocartelle all'interno della cartella, potrebbe essere necessario eliminarle ricorsivamente.


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

    }

Funziona come un fascino. Sia per cartelle che per file. Salam :)


-1

Rimuoverlo da un'altra parte

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

Alcune di queste risposte sembrano inutilmente lunghe:

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

Funziona anche per le sottodirectory.


-3

Puoi usare questa funzione

public void delete()    
{   
    File f = new File("E://implementation1/");
    File[] files = f.listFiles();
    for (File file : files) {
        file.delete();
    }
}

Funziona bene con una directory con tutti i file chiusi. Ma se provato su una directory con file aperti, non funziona. Puoi aiutarmi a trovare un modo per eliminare la cartella nonostante i file aperti
Piyush Rumao

2
Ciò non eliminerà le sottodirectory non vuote.
Pang
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.