如何通过 Java 中的非递归算法删除一个文件夹/目录?我想使用非递归算法以避免StackOverflowErrors
文件夹具有非常深的路径。
有人可以在这方面提供一些建议。
如何通过 Java 中的非递归算法删除一个文件夹/目录?我想使用非递归算法以避免StackOverflowErrors
文件夹具有非常深的路径。
有人可以在这方面提供一些建议。
在蹩脚的伪代码中,因为我没有方便的 Java 编译器来测试它:
queue = [ rootDir ]
stack = []
while ( !queue.isEmpty() ) {
currentDir = queue.take()
stack.push( currentDir )
files = currentDir.list()
for ( f : files ) {
if ( f.isDirectory() ) {
queue.add( f )
} else {
f.delete()
}
}
}
while ( !stack.isEmpty() ) {
f = stack.pop()
f.delete()
}
基本上,这段代码应该扫描一个目录,删除文件或排队子目录以进行进一步扫描。它将扫描的目录放在一个堆栈中,以便第二个while
循环以正确的顺序删除它们(最深的优先)。
这是删除文件/文件夹的一般方法:
/**deletes a file/folder recursively, and returns true iff succeeded */
public static boolean deleteQuietly(File file) {
if (file == null || !file.exists())
return true;
if (!file.isDirectory())
return file.delete();
LinkedList<File> dirs = new LinkedList<>();
dirs.add(0, file);
boolean succeededDeletion = true;
while (!dirs.isEmpty()) {
file = dirs.remove(0);
File[] children = file.listFiles();
if (children == null || children.length == 0)
succeededDeletion &= file.delete();
else {
dirs.add(0, file);
for (File child : children)
if (child.isDirectory())
dirs.add(0, child);
else
succeededDeletion &= child.delete();
}
}
return succeededDeletion;
}
这只是您改进的起点。
关键部分是找出要删除的目录。
这段伪代码应该可以帮助您找出某个目录下的所有目录:
Set<File> allDirectories = new Set<File>();
allDirectories.add(yourStartingDirectory);
while (hasMoreToRead) {
hasMoreToRead = false;
for (File f : allDirectories) {
if (f.isDirectory() && !allDirectories.contains(f)) {
allDirectories.add(f);
hasMoreToRead = true;
}
}
}
这只是一个起点,但您应该能够完成其余的工作:避免重新访问allDirectories
在先前迭代中处理过的目录;基于allDirectories
;执行删除 通过以“正确”顺序删除来提高删除效率;ETC
// Deletes all files and subdirectories under dir.
// Returns true if all deletions were successful.
// If a deletion fails, the method stops attempting to delete and returns false.
public static boolean deleteDir(File dir) {
if (dir.isDirectory()) {
String[] children = dir.list();
for (int i=0; i<children.length; i++) {
boolean success = deleteDir(new File(dir, children[i]));
if (!success) {
return false;
}
}
}
// The directory is now empty so delete it
return dir.delete();
}
要删除递归,您可以用显式堆栈替换调用堆栈以保存您仍需要处理的项目。在您的情况下,您可以跟踪完成当前文件夹后需要删除的所有父文件夹。这是一个使用 LinkedList 作为堆栈的示例:
public static void rmdir(File dir) {
LinkedList<File> dirs = new LinkedList<File>();
dirs.push(dir);
while (dirs.peek() != null) {
dir = dirs.pop();
File[] contents = dir.listFiles();
if (contents.length == 0) {
dir.delete();
} else {
dirs.push(dir);
for(File content : contents) {
if (content.isDirectory()) {
dirs.push(content);
} else {
content.delete();
}
}
}
}
}
我对您的问题的解释是您想删除一个目录而不递归到其中的目录。在这种情况下,您可以使用非常简单的循环来实现删除...
File directory = new File("c:\\directory_path")
if (!directory.exists()){
return;
}
File[] files = directory.listFiles();
for (int i=0;i<files.length;i++){
if (files[i].isFile()){
boolean deleted = files[i].delete();
if (!deleted){
System.out.println("Problem deleting file " + files[i].getAbsolutePath());
}
}
}
这将列出Files
数组中的所有目录,然后遍历它们。如果文件是normal file
,它将被删除。将跳过非正常文件,例如目录。
当然,还有其他类似的替代方案,例如FileFilter
在listFiles()
方法中添加 a 以便数组仅由普通文件填充,但实际上非常相似。
如果要删除目录树,则必须使用某种递归。不过,您可以采用不同的方法来处理它,这可能不会给您带来太多问题,例如构建一个ArrayList
目录,然后ArrayList
一次又一次地删除它们。这将有助于减少递归。
public static final void delete(File file) throws IOException
{
if (!file.exists())
throw new IllegalArgumentException("File does not exist: " + file);
if (file.isFile())
{
simpleDelete(file);
return;
}
Deque<File> dirsQueue = new ArrayDeque<File>();
dirsQueue.push(file);
for (File dir; (dir = dirsQueue.peekLast()) != null;)
{
File[] children = dir.listFiles();
if (children == null)
throw new IOException("Unable to read directory: " + dir);
if (children.length == 0)
{
simpleDelete(dir);
dirsQueue.removeLast();
continue;
}
for (File child : children)
{
if (child.isDirectory())
dirsQueue.addLast(child);
else
simpleDelete(child);
}
}
}
private static final void simpleDelete(File file) throws IOException
{
if (!file.delete())
throw new IOException("Unable to delete " + (file.isDirectory() ? "directory" : "file") + ": " + file);
}