在Java中是否有一种方法可以递归地删除整个目录?
在正常情况下,可以删除空目录。 然而,当涉及到删除包含内容的整个目录时,就不再那么简单了。
如何在Java中删除包含内容的整个目录?
在Java中是否有一种方法可以递归地删除整个目录?
在正常情况下,可以删除空目录。 然而,当涉及到删除包含内容的整个目录时,就不再那么简单了。
如何在Java中删除包含内容的整个目录?
当前回答
如果你有Spring,你可以使用filesystemutils . deleterecursive:
import org.springframework.util.FileSystemUtils;
boolean success = FileSystemUtils.deleteRecursively(new File("directory"));
其他回答
刚刚看到我的解决方案或多或少与埃里克森的相同,只是包装成一个静态方法。把它放到某个地方,它的重量比安装所有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();
}
}
一个有堆栈且没有递归方法的解决方案:
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();
}
}
使用符号链接和上面的代码失败的两种方式…也不知道怎么解决。
方法# 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:
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;
}
}
});
}
我使用它作为特定于平台的方法(在这个未测试的代码中):
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来自Apache Commons Lang。Processes是私有的,但是它的行为应该是明显的。)
如果你有Spring,你可以使用filesystemutils . deleterecursive:
import org.springframework.util.FileSystemUtils;
boolean success = FileSystemUtils.deleteRecursively(new File("directory"));