在Java中是否有一种方法可以递归地删除整个目录?
在正常情况下,可以删除空目录。 然而,当涉及到删除包含内容的整个目录时,就不再那么简单了。
如何在Java中删除包含内容的整个目录?
在Java中是否有一种方法可以递归地删除整个目录?
在正常情况下,可以删除空目录。 然而,当涉及到删除包含内容的整个目录时,就不再那么简单了。
如何在Java中删除包含内容的整个目录?
当前回答
处理异常的最佳解决方案是,方法抛出的异常应该总是描述该方法试图(和失败)做什么:
private void deleteRecursive(File f) throws Exception {
try {
if (f.isDirectory()) {
for (File c : f.listFiles()) {
deleteRecursive(c);
}
}
if (!f.delete()) {
throw new Exception("Delete command returned false for file: " + f);
}
}
catch (Exception e) {
throw new Exception("Failed to delete the folder: " + f, e);
}
}
其他回答
也许这个问题的解决方案是使用erickson回答中的代码重新实现File类的delete方法:
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();
}
}
}
这是一个接受命令行参数的基本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();
}
}
}
我希望这对你有所帮助!
在Guava 9之前,Guava一直支持files . deleterecursive (File)。
来自番石榴10:
弃用。该方法存在符号链接检测差和竞态条件差的问题。只有使用操作系统命令(如rm -rf或del /s)才能适当地支持此功能。这个方法计划在Guava 11.0版本中从Guava中移除。
因此,在番石榴11中没有这种方法。
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是私有的,但是它的行为应该是明显的。)
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;
}
如果您正在处理大型或复杂的目录,值得一试。