在 Java 中递归删除目录
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/779519/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Delete directories recursively in Java
提问by paweloque
Is there a way to delete entire directories recursively in Java?
有没有办法在Java中递归删除整个目录?
In the normal case it is possible to delete an empty directory. However when it comes to deleting entire directories with contents, it is not that simple anymore.
在正常情况下,可以删除一个空目录。但是,当要删除包含内容的整个目录时,就不再那么简单了。
How do you delete entire directories with contents in Java?
如何删除包含 Java 内容的整个目录?
采纳答案by Steve K
You should check out Apache's commons-io. It has a FileUtilsclass that will do what you want.
您应该查看Apache 的 commons-io。它有一个FileUtils类,可以做你想做的事。
FileUtils.deleteDirectory(new File("directory"));
回答by erickson
With Java 7, we can finally do this with reliable symlink detection.(I don't consider Apache's commons-io to have reliablesymlink detection at this time, as it doesn't handle links on Windows created with mklink
.)
使用 Java 7,我们终于可以通过可靠的符号链接检测来做到这一点。(我不认为 Apache 的 commons-io 目前具有可靠的符号链接检测,因为它不处理 Windows 上使用mklink
.
For the sake of history, here's a pre-Java 7 answer, which follows symlinks.
为了历史起见,这里有一个 Java 7 之前的答案,它遵循符号链接。
void delete(File f) throws IOException {
if (f.isDirectory()) {
for (File c : f.listFiles())
delete(c);
}
if (!f.delete())
throw new FileNotFoundException("Failed to delete file: " + f);
}
回答by paweloque
Maybe a solution for this problem might be to reimplement the delete method of the File class using the code from erickson's answer:
也许这个问题的解决方案可能是使用 erickson's answer 中的代码重新实现 File 类的删除方法:
public class MyFile extends File {
... <- copy constructor
public boolean delete() {
if (f.isDirectory()) {
for (File c : f.listFiles()) {
return new MyFile(c).delete();
}
} else {
return f.delete();
}
}
}
回答by glue
Here is a bare bones main method that accepts a command line argument, you may need to append your own error checking or mold it to how you see fit.
这是一个简单的 main 方法,它接受命令行参数,您可能需要附加自己的错误检查或将其塑造成您认为合适的方式。
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
public class DeleteFiles {
/**
* @param intitial arguments take in a source to read from and a
* destination to read to
*/
public static void main(String[] args)
throws FileNotFoundException,IOException {
File src = new File(args[0]);
if (!src.exists() ) {
System.out.println("FAILURE!");
}else{
// Gathers files in directory
File[] a = src.listFiles();
for (int i = 0; i < a.length; i++) {
//Sends files to recursive deletion method
fileDelete(a[i]);
}
// Deletes original source folder
src.delete();
System.out.println("Success!");
}
}
/**
* @param srcFile Source file to examine
* @throws FileNotFoundException if File not found
* @throws IOException if File not found
*/
private static void fileDelete(File srcFile)
throws FileNotFoundException, IOException {
// Checks if file is a directory
if (srcFile.isDirectory()) {
//Gathers files in directory
File[] b = srcFile.listFiles();
for (int i = 0; i < b.length; i++) {
//Recursively deletes all files and sub-directories
fileDelete(b[i]);
}
// Deletes original sub-directory file
srcFile.delete();
} else {
srcFile.delete();
}
}
}
I hope that helps!
我希望这有帮助!
回答by Andrew McKinlay
Guavahad Files.deleteRecursively(File)
supported until Guava 9.
Guava一直Files.deleteRecursively(File)
支持到Guava 9。
From Guava 10:
从番石榴 10:
Deprecated.This method suffers from poor symlink detection and race conditions. This functionality can be supported suitably only by shelling out to an operating system command such as
rm -rf
ordel /s
. This method is scheduled to be removed from Guava in Guava release 11.0.
已弃用。这种方法受到符号链接检测和竞争条件不佳的影响。只能通过对诸如
rm -rf
或 之类的操作系统命令进行外壳来适当地支持此功能del /s
。此方法计划在 Guava 11.0 版中从 Guava 中删除。
Therefore, there is no such method in Guava 11.
因此,Guava 11 中没有这种方法。
回答by Paulitex
Just saw my solution is more or less the same as erickson's, just packaged as a static method. Drop this somewhere, it's much lighter weight than installing all of Apache Commons for something that (as you can see) is quite simple.
刚刚看到我的解决方案与erickson的解决方案或多或少相同,只是打包为静态方法。把它放在某个地方,它比安装所有 Apache Commons 的重量轻得多(如你所见)非常简单。
public class FileUtils {
/**
* By default File#delete fails for non-empty directories, it works like "rm".
* We need something a little more brutual - this does the equivalent of "rm -r"
* @param path Root File Path
* @return true iff the file and all sub files/directories have been removed
* @throws FileNotFoundException
*/
public static boolean deleteRecursive(File path) throws FileNotFoundException{
if (!path.exists()) throw new FileNotFoundException(path.getAbsolutePath());
boolean ret = true;
if (path.isDirectory()){
for (File f : path.listFiles()){
ret = ret && deleteRecursive(f);
}
}
return ret && path.delete();
}
}
回答by Peter
Two ways to fail with symlinks and the above code... and don't know the solution.
使用符号链接和上述代码失败的两种方法......并且不知道解决方案。
Way #1
方式#1
Run this to create a test:
运行这个来创建一个测试:
echo test > testfile
mkdir dirtodelete
ln -s badlink dirtodelete/badlinktodelete
Here you see your test file and test directory:
在这里您可以看到您的测试文件和测试目录:
$ ls testfile dirtodelete
testfile
dirtodelete:
linktodelete
Then run your commons-io deleteDirectory(). It crashes saying the file is not found. Not sure what the other examples do here. The Linux rm command would simply delete the link, and rm -r on the directory would also.
然后运行您的 commons-io deleteDirectory()。它崩溃说找不到文件。不确定其他示例在这里做了什么。Linux rm 命令只会删除链接,目录上的 rm -r 也会删除。
Exception in thread "main" java.io.FileNotFoundException: File does not exist: /tmp/dirtodelete/linktodelete
Way #2
方式#2
Run this to create a test:
运行这个来创建一个测试:
mkdir testdir
echo test > testdir/testfile
mkdir dirtodelete
ln -s ../testdir dirtodelete/dirlinktodelete
Here you see your test file and test directory:
在这里您可以看到您的测试文件和测试目录:
$ ls dirtodelete testdir
dirtodelete:
dirlinktodelete
testdir:
testfile
Then run your commons-io deleteDirectory() or the example code people posted. It deletes not only the directory, but your testfile which is outside the directory being deleted. (It dereferences the directory implicitly, and deletes the contents). rm -r would delete the link only. You need to use something like this delete the dereferenced files: "find -L dirtodelete -type f -exec rm {} \;".
然后运行您的 commons-io deleteDirectory() 或人们发布的示例代码。它不仅会删除目录,还会删除位于被删除目录之外的测试文件。(它隐式地取消引用目录,并删除内容)。rm -r 只会删除链接。您需要使用类似这样的方法删除取消引用的文件:“find -L ditrodelete -type f -exec rm {} \;”。
$ ls dirtodelete testdir
ls: cannot access dirtodelete: No such file or directory
testdir:
回答by AdamOutler
public void deleteRecursive(File path){
File[] c = path.listFiles();
System.out.println("Cleaning out folder:" + path.toString());
for (File file : c){
if (file.isDirectory()){
System.out.println("Deleting file:" + file.toString());
deleteRecursive(file);
file.delete();
} else {
file.delete();
}
}
path.delete();
}
回答by vladicho
static public void deleteDirectory(File path)
{
if (path == null)
return;
if (path.exists())
{
for(File f : path.listFiles())
{
if(f.isDirectory())
{
deleteDirectory(f);
f.delete();
}
else
{
f.delete();
}
}
path.delete();
}
}
回答by Trevor Robinson
Java 7 added support for walking directories with symlink handling:
Java 7 添加了对带有符号链接处理的遍历目录的支持:
import java.nio.file.*;
public static void removeRecursive(Path path) throws IOException
{
Files.walkFileTree(path, new SimpleFileVisitor<Path>()
{
@Override
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs)
throws IOException
{
Files.delete(file);
return FileVisitResult.CONTINUE;
}
@Override
public FileVisitResult visitFileFailed(Path file, IOException exc) throws IOException
{
// try to delete the file anyway, even if its attributes
// could not be read, since delete-only access is
// theoretically possible
Files.delete(file);
return FileVisitResult.CONTINUE;
}
@Override
public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOException
{
if (exc == null)
{
Files.delete(dir);
return FileVisitResult.CONTINUE;
}
else
{
// directory iteration failed; propagate exception
throw exc;
}
}
});
}
I use this as a fallback from platform-specific methods (in this untestedcode):
我将其用作平台特定方法的后备(在此未经测试的代码中):
public static void removeDirectory(Path directory) throws IOException
{
// does nothing if non-existent
if (Files.exists(directory))
{
try
{
// prefer OS-dependent directory removal tool
if (SystemUtils.IS_OS_WINDOWS)
Processes.execute("%ComSpec%", "/C", "RD /S /Q \"" + directory + '"');
else if (SystemUtils.IS_OS_UNIX)
Processes.execute("/bin/rm", "-rf", directory.toString());
}
catch (ProcessExecutionException | InterruptedException e)
{
// fallback to internal implementation on error
}
if (Files.exists(directory))
removeRecursive(directory);
}
}
(SystemUtils is from Apache Commons Lang. Processes is private but its behavior should be obvious.)
( SystemUtils 来自Apache Commons Lang。进程是私有的,但它的行为应该是显而易见的。)