jiafu
jiafu

Reputation: 6556

in java, how to delete one folder/dir by non recursive algorithm?

How can I delete one folder/directory by a non-recursive algorithm in Java? I want to use a non-recursive algorithm in order to avoid StackOverflowErrors when a folder has a very deep path.

Could someone please offer some advise in this area.

Upvotes: 2

Views: 2202

Answers (7)

android developer
android developer

Reputation: 116080

Here's a general way to delete a file/folder :

/**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;
}

Upvotes: 3

Venkata Raju
Venkata Raju

Reputation: 5231

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);
}

Upvotes: 0

Edward Samson
Edward Samson

Reputation: 2425

To remove recursion, you replace the call stack with an explicit stack to hold the items you still need to process. In your case, you keep track of all the parent folders you need to delete after you are done with the current one. Here's an example using a LinkedList as a stack:

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();
                }
            }
        }
    }
}

Upvotes: 1

lhballoti
lhballoti

Reputation: 806

In crappy pseudo-code, as I don't have a Java compiler handy to test this:

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()
}

Basically this code should scan a directory, deleting files or queueing subdirectories for further scanning. It places scanned directories in a stack, so that the second while loop deletes them in the correct order (deepest first).

Upvotes: 4

XU3352
XU3352

Reputation: 145

// 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();
}

Upvotes: 1

Adrian Shum
Adrian Shum

Reputation: 40076

this is just a starting point for you to improve on.

The critical part is to find out what's the directories to delete.

This piece of psuedo code should help you to find out all directories under certain directory:

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;
    }
  }
}

This is just a starting point, but you should be able to finish the rest: Avoid revisiting directories in allDirectories that has been processed in previous iterations; Performing delete base on allDirectories; Make the delete more efficient by deleting in "correct" order; etc

Upvotes: 1

wattostudios
wattostudios

Reputation: 8774

My interpretation of your question is that you want to delete a directory without recursing into the directories within it. In this case, you can implement the deletion using a pretty simple loop...

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());
        }
    }
}

This will list all the Files of the directory in an array, and then loop through them. If the file is a normal file, it will be deleted. Non-normal files, such as directories, will be skipped.

Of course, there are other similar alternatives, such as adding a FileFilter to the listFiles() method so that the array is only populated by normal files, but its effectively pretty similar.

If you want to delete the directory tree, you will have to use some kind of recursion. You could approach it differently though, which might not cause you so many problems, such as building an ArrayList of directories, and then iterating through the ArrayList deleting them one at a time. This would help to reduce the recursion.

Upvotes: 0

Related Questions