在Java中是否有一种方法可以递归地删除整个目录?
在正常情况下,可以删除空目录。 然而,当涉及到删除包含内容的整个目录时,就不再那么简单了。
如何在Java中删除包含内容的整个目录?
在Java中是否有一种方法可以递归地删除整个目录?
在正常情况下,可以删除空目录。 然而,当涉及到删除包含内容的整个目录时,就不再那么简单了。
如何在Java中删除包含内容的整个目录?
当前回答
使用符号链接和上面的代码失败的两种方式…也不知道怎么解决。
方法# 1
运行这个来创建一个测试:
echo test > testfile
mkdir dirtodelete
ln -s badlink dirtodelete/badlinktodelete
下面你可以看到你的测试文件和测试目录:
$ ls testfile dirtodelete
testfile
dirtodelete:
linktodelete
然后运行common -io deleteDirectory()。它崩溃,说文件没有找到。不知道其他例子是怎么做的。Linux的rm命令会简单地删除链接,目录上的rm -r也会删除链接。
Exception in thread "main" java.io.FileNotFoundException: File does not exist: /tmp/dirtodelete/linktodelete
方法# 2
运行这个来创建一个测试:
mkdir testdir
echo test > testdir/testfile
mkdir dirtodelete
ln -s ../testdir dirtodelete/dirlinktodelete
下面你可以看到你的测试文件和测试目录:
$ ls dirtodelete testdir
dirtodelete:
dirlinktodelete
testdir:
testfile
然后运行common -io deleteDirectory()或人们发布的示例代码。它不仅会删除目录,还会删除位于被删除目录之外的testfile。(它隐式地取消对目录的引用,并删除内容)。Rm -r只会删除链接。你需要使用类似这样的方法删除被解引用的文件:"find -L dirtodelete -type f -exec rm {} \;"
$ ls dirtodelete testdir
ls: cannot access dirtodelete: No such file or directory
testdir:
其他回答
rm -rf的性能比FileUtils.deleteDirectory要好得多。
经过大量的基准测试后,我们发现使用rm -rf比使用FileUtils.deleteDirectory快几倍。
当然,如果您有一个小的或简单的目录,这并不重要,但在我们的例子中,我们有多个gb和深度嵌套的子目录,使用FileUtils.deleteDirectory需要10分钟以上,使用rm -rf只需1分钟。
下面是我们粗略的Java实现:
// Delete directory given and all subdirectories and files (i.e. recursively).
//
static public boolean deleteDirectory( File file ) throws IOException, InterruptedException {
if ( file.exists() ) {
String deleteCommand = "rm -rf " + file.getAbsolutePath();
Runtime runtime = Runtime.getRuntime();
Process process = runtime.exec( deleteCommand );
process.waitFor();
return true;
}
return false;
}
如果您正在处理大型或复杂的目录,值得一试。
刚刚看到我的解决方案或多或少与埃里克森的相同,只是包装成一个静态方法。把它放到某个地方,它的重量比安装所有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();
}
}
在Guava 9之前,Guava一直支持files . deleterecursive (File)。
来自番石榴10:
弃用。该方法存在符号链接检测差和竞态条件差的问题。只有使用操作系统命令(如rm -rf或del /s)才能适当地支持此功能。这个方法计划在Guava 11.0版本中从Guava中移除。
因此,在番石榴11中没有这种方法。
虽然可以使用file.delete()轻松删除文件,但要删除的目录必须为空。使用递归可以很容易地做到这一点。例如:
public static void clearFolders(String[] args) {
for(String st : args){
File folder = new File(st);
if (folder.isDirectory()) {
File[] files = folder.listFiles();
if(files!=null) {
for(File f: files) {
if (f.isDirectory()){
clearFolders(new String[]{f.getAbsolutePath()});
f.delete();
} else {
f.delete();
}
}
}
}
}
}
一个有堆栈且没有递归方法的解决方案:
File dir = new File("/path/to/dir");
File[] currList;
Stack<File> stack = new Stack<File>();
stack.push(dir);
while (! stack.isEmpty()) {
if (stack.lastElement().isDirectory()) {
currList = stack.lastElement().listFiles();
if (currList.length > 0) {
for (File curr: currList) {
stack.push(curr);
}
} else {
stack.pop().delete();
}
} else {
stack.pop().delete();
}
}