Comment supprimer un dossier avec des fichiers à l'aide de Java

104

Je souhaite créer et supprimer un répertoire à l'aide de Java, mais cela ne fonctionne pas.

File index = new File("/home/Work/Indexer1");
if (!index.exists()) {
    index.mkdir();
} else {
    index.delete();
    if (!index.exists()) {
        index.mkdir();
    }
}
Monsieur G
la source
3
Que s'est-il passé lorsque vous avez essayé?
Abimaran Kugathasan
Quelle est la question?
Aniket Thakur
1
le fichier d'index n'est pas supprimé.
Mr.G
1
Reportez-vous Comment supprimer un répertoire en Java
Aniket Thakur
1
Malheureusement, @AniketThakur, cette approche suivra des liens symboliques et supprimera les fichiers et répertoires qui n'étaient peut-être pas prévus.
Hank Schultz

Réponses:

99

Java ne peut pas supprimer les dossiers contenant des données. Vous devez supprimer tous les fichiers avant de supprimer le dossier.

Utilisez quelque chose comme:

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

Ensuite, vous devriez pouvoir supprimer le dossier en utilisant index.delete() Non testé!

Cemron
la source
37
Cela ne supprimera pas les sous-répertoires non vides.
Francesco Menzani
13
vous devez écrire une méthode récursive ou utiliser FileUtils.deleteDirectorycomme @Francesco Menzani l'a dit.
EN20
4
Soyez très prudent. Si l'index est un lien symbolique vers un autre répertoire, vous finirez par supprimer le contenu de l'autre répertoire. Malheureusement, je n'ai pas encore trouvé un bon moyen de détecter les liens symboliques sous Windows dans Java 6, bien que Java 7 fournisse Files.isSymbolicLink ().
Hank Schultz
1
Solution: enroulez ce morceau de code if (!index.delete()) {...}. Ensuite, si l'index est un lien symbolique, il est supprimé indépendamment du fait qu'il semble avoir un contenu.
Hank Schultz
Cela lèvera une NullPointerException s'il y a une exception d'E / S lors de la lecture du répertoire. Le code doit vérifier si entriesest nul.
mernst
178

Juste une seule ligne.

import org.apache.commons.io.FileUtils;

FileUtils.deleteDirectory(new File(destination));

Documentation ici

Barry Knapp
la source
13
um non. Il s'agit d'un one-liner avec une dépendance externe, ce qui est une chose importante à garder à l'esprit. Le seul moment où vous utilisez une dépendance externe comme celle-ci est aussi simple que lorsque vous faites un projet de maison personnelle ou que votre entreprise ne se soucie vraiment pas de la possibilité d'être poursuivie.
searchengine27
11
@ searchengine27 mais il semble que la bibliothèque soit sous Apache Commons, donc le risque d'être poursuivi est négligeable whitesourcesoftware.com/whitesource-blog/… .
simtim
1
@simtim vous manquez complètement le point. Une entreprise n'approuvera jamais une bibliothèque à utiliser sans qu'une équipe d'avocats se soit penchée sur les conditions d'utilisation et les accords avec l'utilisateur final, ainsi que sur tout autre document juridique associé à la bibliothèque. Quelqu'un doit payer ces avocats ... parfois personne ne veut, ce qui signifie que le développeur ne peut pas l'utiliser. Plus l'entreprise pour laquelle vous travaillez est grande, plus vous devez passer par des formalités administratives.
searchengine27
19
@ searchengine27 non, vous manquez complètement le point. Une entreprise qui a besoin d'une armée d'avocats pour autoriser l'utilisation d'apache commons est la pathologie absolue, et rien de comparable dans le monde informatique. Je n'ai jamais entendu parler de quiconque ayant de tels problèmes et si vous avez de tels problèmes, vous avez probablement un accès à SO bloqué, de sorte que la réponse ne vous sera pas accessible de toute façon.
9ilsdx 9rvj 0lo
94

Cela fonctionne, et même s'il semble inefficace de sauter le test de répertoire, ce n'est pas le cas: le test se déroule tout de suite dans listFiles().

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

Mettre à jour, pour éviter les liens symboliques suivants:

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
la source
2
En fait, il y a un bug là-dedans. Si un autre processus supprime les fichiers pendant la boucle, il peut provoquer une exception qui doit être interceptée et ignorée.
Jeff Learman
2
@ 9ilsdx9rvj0lo Plutôt que d'être sournois, vous pourriez peut-être fournir une modification pour gérer les liens symboliques. Le PO n'a rien dit sur les liens symboliques dans son message. Créer et supprimer simplement un répertoire. Veuillez également énumérer les «nombreuses choses manquantes». Aidez-nous.
Perry Tew
@PerryTew Je ne suis pas sournois. Je signale simplement que je ne suis pas du tout d'accord avec votre commentaire selon lequel la réponse est meilleure parce qu'aucune bibliothèque externe n'est utilisée. Ce n'est pas. Il y a une bonne raison pour laquelle les gens utilisent apache commons: vous n'avez rien à programmer vous-même. Les liens symboliques ne sont qu'un exemple de choses qui vous manqueront d'écrire tout à partir de zéro.
9ilsdx 9rvj 0lo
2
Ce n'est pas une question de meilleur / pire, mais des avantages et des inconvénients. Ne pas compter sur des bibliothèques externes est parfois un avantage significatif. Bien sûr, il y a un avantage significatif à utiliser un logiciel éprouvé. C'est au développeur d'équilibrer les problèmes. S'il y a des bogues autres que les deux déjà mentionnés, nous aimerions certainement les connaître.
Jeff Learman
31

Je préfère cette solution sur java 8:

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

Depuis ce site: http://www.baeldung.com/java-delete-directory

nirmal
la source
2
Notez que cela peut avoir des problèmes d'évolutivité car il génère la liste complète, crée une copie triée, puis itère sur la copie triée. À l'époque où la mémoire n'était pas inépuisable, ce serait une très mauvaise idée. C'est concis mais à un coût en espace (O (N) vs O (1)) et en efficacité (O (N log N) vs O (N)). Cela n'aurait pas d'importance dans la plupart des cas d'utilisation.
Jeff Learman
J'aurais dû dire "espace O (N) vs O (profondeur)" ci-dessus, où la profondeur est la profondeur de l'arborescence des répertoires (en comparant cette solution aux solutions récursives.)
Jeff Learman
1
c'est élégant, fonctionne et ne repose pas sur des bibliothèques externes. aimé
Leo
Cela n'a-t-il pas le problème des fuites de descripteurs de fichiers? Cet exemple ne ferme pas le flux renvoyé par Files.walk(), ce qui est explicitement indiqué dans la documentation de l'API. Je sais que si vous ne fermez pas le flux renvoyé par, Files.list()par exemple, vous pouvez manquer de poignées et le programme plantera. Voir par exemple stackoverflow.com/q/36990053/421049 et stackoverflow.com/q/26997240/421049 .
Garret Wilson
24

Dans JDK 7, vous pouvez utiliser Files.walkFileTree()et Files.deleteIfExists()supprimer une arborescence de fichiers. (Exemple: http://fahdshariff.blogspot.ru/2011/08/java-7-deleting-directory-by-walking.html )

Dans JDK 6, une manière possible est d'utiliser FileUtils.deleteQuietly d'Apache Commons qui supprimera un fichier, un répertoire ou un répertoire avec des fichiers et des sous-répertoires.

Andrey Chaschev
la source
6
Voici un échantillon: fahdshariff.blogspot.ru/2011/08/…
Andrey Chaschev
23

En utilisant Apache Commons-IO, il suit une ligne:

import org.apache.commons.io.FileUtils;

FileUtils.forceDelete(new File(destination));

C'est (légèrement) plus performant que FileUtils.deleteDirectory.

JRA_TLL
la source
groupe: 'commons-io', nom: 'commons-io', version: '2. +' - utile
mike rodent
10

Comme mentionné, Java ne peut pas supprimer un dossier contenant des fichiers, supprimez donc d'abord les fichiers, puis le dossier.

Voici un exemple simple pour faire ceci:

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

Ou:

FileUtils.forceDelete(new File(destination));
Gavriel Cohen
la source
9

Ma version récursive de base, fonctionnant avec les anciennes versions de JDK:

public static void deleteFile(File element) {
    if (element.isDirectory()) {
        for (File sub : element.listFiles()) {
            deleteFile(sub);
        }
    }
    element.delete();
}
Pierre Lemée
la source
2
Cela lèvera une NullPointerException s'il y a une exception d'E / S lors de la lecture du répertoire. Le code doit vérifier si listFiles()renvoie null, plutôt que d'appeler isDirectory().
2017
9

C'est la meilleure solution pour 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
la source
6

Guava 21+ à la rescousse. À utiliser uniquement s'il n'y a aucun lien symbolique pointant vers le répertoire à supprimer.

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

(Cette question est bien indexée par Google, donc d'autres personnes utilisant Guava pourraient être heureuses de trouver cette réponse, même si elle est redondante avec d'autres réponses ailleurs.)

Laurent Caillette
la source
4

J'aime le plus cette solution. Il n'utilise pas de bibliothèque tierce, mais utilise NIO2 de 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
la source
3

Un autre choix consiste à utiliser la org.springframework.util.FileSystemUtilsméthode pertinente de Spring qui supprimera récursivement tout le contenu du répertoire.

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

Cela fera l'affaire!

dZ.
la source
2

Dans ce

index.delete();

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

vous appelez

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

après

index.delete();

Cela signifie que vous créez à nouveau le fichier après la suppression de File.delete () renvoie une valeur booléenne.Donc si vous voulez vérifier, faites System.out.println(index.delete());si vous obtenez truecela signifie que le fichier est supprimé

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
               }




        }

à partir des commentaires ci-dessous, la réponse mise à jour est comme ceci

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
la source
2

Si vous avez des sous-dossiers, vous trouverez des problèmes avec les réponses Cemron. vous devez donc créer une méthode qui fonctionne comme ceci:

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
la source
2

Vous pouvez utiliser FileUtils.deleteDirectory . JAVA ne peut pas supprimer les dossiers non vides avec File.delete () .

Issam Ressani
la source
1

Directry ne peut pas simplement supprimer s'il contient les fichiers, vous devrez peut-être supprimer les fichiers à l'intérieur d'abord, puis le répertoire

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
la source
1

Vous pouvez effectuer un appel récursif si des sous-répertoires existent

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
la source
1

nous pouvons utiliser la spring-coredépendance;

boolean result = FileSystemUtils.deleteRecursively(file);
Kanagavelu Sugumar
la source
1

La plupart des réponses (même récentes) faisant référence aux classes JDK s'appuient sur, File.delete()mais il s'agit d'une API défectueuse car l'opération peut échouer silencieusement.
La java.io.File.delete()documentation de la méthode indique:

Notez que la java.nio.file.Filesclasse définit la deleteméthode à lancer IOExceptionlorsqu'un fichier ne peut pas être supprimé. Ceci est utile pour le rapport d'erreurs et pour diagnostiquer pourquoi un fichier ne peut pas être supprimé.

En remplacement, vous devriez privilégier Files.delete(Path p) qui jette un IOExceptionavec un message d'erreur.

Le code réel pourrait être écrit tel que:

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
la source
0

vous pouvez essayer comme suit

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

S'il y a des sous-dossiers dans votre dossier, vous devrez peut-être les supprimer de manière récursive.

Ruchira Gayan Ranaweera
la source
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
la source
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();
        }

    }

Fonctionne comme un charme. Pour les dossiers et les fichiers. Salam :)

Mushtaque Ahmed
la source
-1

Retirez-le d'une autre partie

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
la source
-1

Certaines de ces réponses semblent inutilement longues:

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

Fonctionne aussi pour les sous-répertoires.

Adam court
la source
-3

Vous pouvez utiliser cette fonction

public void delete()    
{   
    File f = new File("E://implementation1/");
    File[] files = f.listFiles();
    for (File file : files) {
        file.delete();
    }
}
Piyush Rumao
la source
Cela fonctionne bien avec un répertoire avec tous les fichiers fermés. Mais lorsqu'il est essayé sur un répertoire avec des fichiers ouverts, cela ne fonctionne pas. Pouvez-vous m'aider à trouver un moyen de supprimer le dossier malgré les fichiers ouverts
Piyush Rumao
2
Cela ne supprimera pas les sous-répertoires non vides.
Pang