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

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


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



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

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


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.



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.


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

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

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

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


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

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!


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

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

2

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


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

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

1

nous pouvons utiliser la spring-coredépendance;

boolean result = FileSystemUtils.deleteRecursively(file);

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

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.


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

    }

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


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

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


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

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
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.