Hello guys,

I'm completely losing it. The question asks to emplement an electronic directory traverse in size a chosen folder (using JFileChooser)and print the structure with the calculated the size of each folder and file.

Finding the file size is easy using File.io getSize(). However, to find the size of the folder I wrote the function below to do it.

My problem: My code is totally not calculating the inner folders' size, only the root folder size is being calculated. I think I have a problem in my traverse method?

Traverse Class:

import java.io.File;

public class Traverser 
{
    private File fileObject;
    public Folder originalFolder; //Selected Folder
    public Folder childFolder; // Changes each round of recursion
    public Traverser(File fileObject) 
    {
        this.fileObject = fileObject;
        this.originalFolder = new Folder(fileObject);
    }
    public void letsTraverse()
    {
        recursiveTraversal(this.fileObject, this.originalFolder);
    }
    private void recursiveTraversal(File fileObject, Folder parentFolder) 
    {
        if (fileObject.isDirectory()) 
        { 
            File files[] = fileObject.listFiles();
            for (File afile : files) 
            {
                if (afile.isDirectory()) {
                    this.childFolder = new Folder(afile);
                    parentFolder.add(childFolder);
                }
                recursiveTraversal(afile, this.childFolder);
            }
        } else if (fileObject.isFile()) {
            this.originalFolder.add(new file(fileObject));
        }
    }
}

Folder Class:

import java.util.ArrayList;
import java.io.File;

public class Folder extends Documents
{
    private ArrayList<Documents> filesStack;

    public Folder(File folder)
    {
        this.filesStack = new ArrayList<Documents>();
        this.name = folder.getName();
    }
    public void add(Documents doc)
    {
        this.filesStack.add(doc);
    }
    public long getSize()
    {   
        for (Documents folder: filesStack)
        {
            this.size += folder.getSize(); // sum the size of childfiles
        }
        return this.size;
    }
    public void setName(String name)
    {
        this.name = name;
    }   
    public String toString()
    {
        String result = name + "\t{Folder Size =" + readableFileSize(this.getSize()) + "}";

        // I think I'm missing something, only the first folder
        // size is being calculated
        for (Documents elements: filesStack)
        {
            result += "\n  " + elements.toString();
        }
        return result;
    }
}

Output as Image (Sorry):
https://www.dropbox.com/s/peetbuuo51xdynq/2014-04-05%2003.52.57%20pm.png

for (File afile : files) {
   if (afile.isDirectory()) {
      this.childFolder = new Folder(afile);
      parentFolder.add(childFolder);
   }
    recursiveTraversal(afile, this.childFolder);
}

If the first n Files are files (not directories) the variable childFolder is noy set and presumably inherits some left-over value from a previous class?

ps: This kind of thing is much easier using the current I/O classes in Java 7/8 ("NIO" or "NIO2") rather than the old File class.

Thanks for your reply James.

I think I missput the word here. afile could actually be a folder or a file.

I'm sure my issue has something to do with recursion. Not to mention recursion is not my best mate at all.

I've used NIO at all and I have to test it out and probably write the whole code?

Yes aFile could be either, but if on the first pass of the loop aFile is not a directory then the call to recursiveTravesrsal (line 6 above) is made using some random value of childFolder.
childFolder is only correctly initialised when the for loop processes a directory

Yes, NIO is so different that your would start again, but it does use better programming patterns that are used massively in Java 8

Edited 2 Years Ago by JamesCherrill

It really pains me to see people struggling with Pre-7 Java code when Java 7 includes far better alternatives. This is one of those cases, where the NIO classes in Java 7 are a vast improvement over the old File class.
To demonstrate this point, here's an NIO program to display the sizes of a dir and all all it's recursive sub directories.

It uses the Files.walkFileTree method that, given a starting directory and a file visitor, recursively walks the whole tree calling the file visitor as it goes.
The file visitor, at its simplest, has just three methods - one called when the walker first enters a directory, one called when it finishes a directory, and one called when it processes a file.

This file visitor just uses a stack to hold the nested directory sizes. It pushes a new entry when starting a directory, adds the file size to it when it processes a file, and displays it when finishing a directory (not forgetting to add its size to the parent dir's size).
Here's the whole code:

class SimpleDirWalker extends SimpleFileVisitor<Path> {
    // simple (simplest?) code to list sizes of dirs and sub-dirs

    Deque<Long> dirStack = new ArrayDeque<>(); // current directory sizes 

    @Override
    public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) {
        dirStack.push(new Long(0));
        return CONTINUE;
    }

    @Override
    public FileVisitResult visitFile(Path file, BasicFileAttributes attr) {
        dirStack.push(dirStack.pop()+attr.size());
        return CONTINUE;
    }

    @Override
    public FileVisitResult postVisitDirectory(Path dir, IOException exc) {
        long size = dirStack.pop();
        System.out.println(dir + " = " + size + " bytes");
        if (!dirStack.isEmpty()) // add this dir size to parent's size
            dirStack.push(dirStack.pop() + size);
        return CONTINUE;
    }
}

To use that you just need to call Files.walkFileTree, eg

    File dir = new File("."); // we will walk this dir and everything in it
    SimpleDirWalker dw = new SimpleDirWalker();
    try {
        Files.walkFileTree(dir.toPath(), dw);
    } catch (IOException ex) {
        ex.printStackTrace();
    }

... and that's all!

This question has already been answered. Start a new discussion instead.