如何使用Java删除包含文件的文件夹


104

我想使用Java创建和删除目录,但是它不起作用。

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

3
当您尝试时发生了什么?
Abimaran Kugathasan

有什么问题
Aniket Thakur 2013年

1
索引文件无法删除。
G先生2013年


1
不幸的是,@ AniketThakur,该方法将遵循符号链接,并删除可能不想要的文件和目录。
汉克·舒尔茨2015年

Answers:


99

Java无法删除其中包含数据的文件夹。您必须先删除所有文件,然后再删除文件夹。

使用类似:

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

然后,您应该可以使用index.delete() Untested 删除文件夹!


37
这不会删除非空子目录。
Francesco Menzani 2015年

13
您必须编写递归方法或使用FileUtils.deleteDirectory@Francesco Menzani所说的方法。
2015年

4
要特别小心。如果index是到另一个目录的符号链接,您将删除另一个目录的内容。不幸的是,尽管Java 7提供了Files.isSymbolicLink(),但我还没有找到在Windows 6中检测Windows符号链接的好方法。
汉克·舒尔茨2015年

1
解决方案:将这段代码包装在中if (!index.delete()) {...}。然后,如果index是符号链接,则无论它是否显示内容,都将其删除。
汉克·舒尔茨2015年

如果在读取目录时发生I / O异常,则将抛出NullPointerException。该代码应检查是否entries为空。
mernst

178

只是一线。

import org.apache.commons.io.FileUtils;

FileUtils.deleteDirectory(new File(destination));

这里的文件



13
不。这是一个具有外部依赖关系的单线,这是要牢记的重要事情。唯一使用这样的外部依赖项的时候就这么简单,这是在您进行个人家庭项目时,或者您的公司确实不在乎被起诉的可能性。
searchengine27年

11
@ searchengine27但似乎图书馆是在Apache下议院所以被起诉的风险可以忽略不计whitesourcesoftware.com/whitesource-blog/...
–simtim

1
@simtim,您完全错过了要点。在没有律师团队倾注使用条款和最终用户协议以及与图书馆相关的任何其他法律文件之前,公司永远不会批准图书馆的使用。有人必须付钱给那些律师...有时没人愿意付钱,这意味着开发人员无法使用它。您工作的公司越大,您必须经历的繁文tape节越多。
searchengine27

19
@ searchengine27不,您完全忘记了要点。一个需要大量律师允许使用apache commons的公司是绝对的病态,在IT世界中没有什么比这更规范的了。我从来没有听说过有人遇到这样的问题,如果您遇到这样的问题,那么您很可能无法访问SO,因此无论如何您都无法获得答案。
9ilsdx 9rvj 0lo 18-3-20

94

这可行,尽管跳过目录测试看起来效率低下,但事实并非如此:测试立即在中进行listFiles()

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

更新,以避免出现以下符号链接:

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
事实证明,这是一个错误。如果另一个进程在循环过程中删除了文件,则可能导致异常,应将其捕获并忽略。
杰夫·里尔曼

2
@ 9ilsdx9rvj0lo与其说是笨拙,不如您可以提供编辑以处理符号链接。OP 在他的帖子中没有提及符号链接。只需创建和删除目录。还请列出“许多遗漏的东西”。帮助我们。
Perry Tew

@PerryTew我不是在偷偷摸摸。我只是指出,我完全不同意您关于答案更好的评论,因为没有使用任何外部库。它不是。人们使用apache commons有一个很好的理由:您不必自己编写任何东西。符号链接只是您可能会从头开始编写所有内容的示例。
9ilsdx 9rvj 0lo 18-3-22

2
这不是更好/更坏的问题,而是利弊。不依赖外部库有时会带来很大的好处。当然,使用久经考验的软件有很大的好处。由开发人员来平衡问题。如果除了已经提到的两个错误之外,还有其他错误,我们当然希望了解它们。
杰夫·里尔曼

31

我更喜欢在Java 8上使用此解决方案:

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

从此站点:http : //www.baeldung.com/java-delete-directory


2
请注意,这可能会导致可伸缩性问题,因为它会构建完整列表,创建排序后的副本,然后遍历排序后的副本。追溯到记忆力不竭的糟糕年代,这将是一个非常糟糕的主意。简明扼要,但以空间(O(N)vs O(1))和效率(O(N log N)vs O(N))为代价。在大多数用例中,这无关紧要。
杰夫·里尔曼

我应该在上面说过“空间O(N)vs O(depth)”,其中depth是目录树的深度(将此解决方案与递归解决方案进行比较。)
Jeff Learman

1
这是优雅的,有效的并且不依赖外部库。喜欢它
Leo

这不是文件句柄泄漏的问题吗?此示例关闭Files.walk()API文档中明确指示的由返回的流。我知道,如果不关闭Files.list()例如返回的流,则可能用完了句柄,程序将崩溃。参见例如stackoverflow.com/q/36990053/421049stackoverflow.com/q/26997240/421049
Garret Wilson


23

使用Apache Commons-IO,它遵循以下一种做法:

import org.apache.commons.io.FileUtils;

FileUtils.forceDelete(new File(destination));

(略)胜过FileUtils.deleteDirectory


组:“ commons-io”,名称:“ commons-io”,版本:“ 2. +”-有用
麦克·啮齿动物,

10

如前所述,Java无法删除包含文件的文件夹,因此先删除文件,然后再删除文件夹。

这是执行此操作的一个简单示例:

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

要么:

FileUtils.forceDelete(new File(destination));

9

我的基本递归版本,与旧版本的JDK一起使用:

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

2
如果在读取目录时发生I / O异常,则将抛出NullPointerException。该代码应检查是否listFiles()返回null,而不是调用isDirectory()
蒙斯特(Mernst),

9

这是以下方面的最佳解决方案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

番石榴21+救援。仅当没有符号链接指向要删除的目录时才使用。

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

(此问题已由Google很好地索引,因此其他人usig Guava可能很乐意找到此答案,即使它与其他地方的其他答案是多余的。)


4

我最喜欢这种解决方案。它不使用3rd party库,而是使用Java 7的NIO2

/**
 * 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

另一种选择是使用Spring的org.springframework.util.FileSystemUtils相关方法,该方法将递归删除目录的所有内容。

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

这样就可以了!


2

在这个

index.delete();

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

你在打电话

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

index.delete();

这意味着,你正在删除后重新创建文件 File.delete() ,如果你想检查然后做返回boolean value.So System.out.println(index.delete());如果你得到true那么这意味着文件被删除

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
               }




        }

从下面给出的评论中,更新后的答案是这样的

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

如果您有子文件夹,您将发现Cemron答案的问题。因此,您应该创建一个如下所示的方法:

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


1

Directry不能简单地删除包含文件的文件,因此您可能需要先删除文件然后再删除目录

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

如果子目录存在,则可以进行递归调用

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

引用JDK类的大多数答案(甚至是最近的答案)都依赖于此,File.delete()但这是有缺陷的API,因为操作可能会静默失败。
java.io.File.delete()方法文档状态:

请注意,java.nio.file.Files该类定义了当无法删除文件时delete抛出的方法IOException。这对于错误报告和诊断为什么无法删除文件很有用。

作为替换,您应该支持Files.delete(Path p) 抛出IOException带有错误消息的。

实际的代码可以这样写:

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

您可以尝试如下

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

如果文件夹中有子文件夹,则可能需要递归删除它们。



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

    }

奇迹般有效 。对于文件夹和文件。萨拉姆:)


-1

从其他部分删除

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

其中一些答案似乎不必要地冗长:

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

也适用于子目录。


-3

您可以使用此功能

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

它适用于所有关闭文件的目录。但是,当尝试在具有打开文件的目录上使用时,它不起作用。您能帮助我找到一种
尽管

2
这不会删除非空子目录。
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.