Walking through a file tree

I’ve recently been looking at classes in the java.nio.file package. In particular I’ve been learning how to use Class SimpleFileVisitor in order to visit each file in a file tree. This provides a way of walking through a file tree enabling one to look at files and directories, carrying out whatever actions are required depending upons ones needs.

One interesting caveat is that the method ‘postVisitDirectory’ is:

Invoked for a directory after entries in the directory, and all of their descendants, have been visited.

So if you have lots of subdirectories under a particular directory, this method isn’t executed until you reach the bottom of that part of the branch and then start to come up again.

To test this out, in the preVisitDirectory and postVisitDirectory methods, I placed print statements to give me an idea of what was going on.

preVisitDirectory
msg = String.format("in --> We're just about to look in directory %s%n",
dir.toAbsolutePath().toString());

i.e. "in --> We're just about to look in directory C:\test_a\test_e"

and

postVisitDirectory
msg = String.format("out ++> %s done%n", dir.toAbsolutePath().toString());

i.e. "out ++> C:\test_a\test_e done"

This way I could see where when I went into a directory and when I left it again.

If we have a directory tree such as:


C:\TEST_A
+---test_b
¦   +---test_c
¦       +---test_d
+---test_e

the outcome of my program will be:

in --> We're just about to look in directory C:\test_a

Looked at file: temp_files.ps1

in --> We're just about to look in directory C:\test_a\test_b

Looked at file: test_b01.tmp

Looked at file: test_b02.tmp

in --> We're just about to look in directory C:\test_a\test_b\test_c

Looked at file: test_c01.tmp

Looked at file: test_c02.tmp

in --> We're just about to look in directory C:\test_a\test_b\test_c\test_d

Looked at file: test_d01.tmp

Looked at file: test_d02.tmp

out ++> C:\test_a\test_b\test_c\test_d done

out ++> C:\test_a\test_b\test_c done

out ++> C:\test_a\test_b done

in --> We're just about to look in directory C:\test_a\test_e

Looked at file: test_e01.tmp

Looked at file: test_e02.tmp

out ++> C:\test_a\test_e done

out ++> C:\test_a done

The postVisitDirectory for C:\test_a\test_b\test_c for example, is not mentioned until we leave C:\test_a\test_b\test_c\test_d and start on our way back up.

Directory C:\test_a is the first and last to be visited.
 

The program that I came up with is shown below.


// Copyright (c) 2002 MyHouse
//package ian;
import java.io.IOException;
import java.nio.file.FileVisitResult;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.SimpleFileVisitor;
import java.nio.file.attribute.BasicFileAttributes;
import static java.nio.file.FileVisitResult.*;
import java.util.List;
import java.util.ArrayList;
import java.util.Iterator;
/**
 * @author Ian Molloy March 2013
 * @version (#)coreJava.java        1.05 2013-02-27
 */
public class coreJava {
private byte dummy;
private List<String> pathTaken;
private String msg;
private int fileCount;
private int dirCount;
  /**
   * Constructor
   */
  public coreJava() {
    this.dummy = 99;
    this.fileCount = 0;
    this.dirCount = 0;
    this.pathTaken = new ArrayList<String>(100);
    this.msg = "";
System.out.println("blob constructor for coreJava complete");
    launchFrame();
  }

  /**
   * Adds an item to variable pathTaken.
   */
  private void append2Pathtaken(String item) {
     this.pathTaken.add(item);
  }

  /**
   * Working test method.
   * Floating point formatting to decimal places: %.2f
   * A format of %03d will pad, for example, a 5 to 005.
   * topLevel.setLocationRelativeTo(null);
   */
  public void launchFrame() {
    System.out.printf("Start of test on %tc%n", new java.util.Date());
    // ---------------------------------------------------------------

    Path startDir = Paths.get("C:\\test_a");
    PrintFiles pfiles = new PrintFiles();

    try {
      Files.walkFileTree(startDir, pfiles);
    } catch (IOException e) {
      e.printStackTrace();
    } finally {
      System.out.println("Should be all done now");
    }

/**
    if (pathTaken.size() > 0) {
       System.out.println("\nListing the contents of variable pathTaken");
       for (Iterator<String> iter = pathTaken.iterator(); iter.hasNext(); ) {
          System.out.println(iter.next());
       }
    }
*/

    System.out.printf("%nvariable dummy is now %d%n", dummy);

    // ---------------------------------------------------------------
    System.out.printf("End of test on %tc%n", new java.util.Date());
  }//end of launchFrame

  /**
   * main
   * @param args
   */
  public static void main(String[] args) {
    javax.swing.SwingUtilities.invokeLater(new Runnable() {
      public void run() {
        new coreJava();
      }
    });
  }//end of main

// ==============================================
// Start of inner class
// ==============================================

public class PrintFiles extends SimpleFileVisitor<Path> {
private int dirCount;
private boolean printFilecount;
private String msg;
  /**
   * Constructor
   */
  public PrintFiles() {
    super();
    this.msg = "";
    this.printFilecount = true;
  }//end of constructor

  private void printBklanklines(int blanks) {

     for (int m = 0; m < blanks; m++) {
         System.out.println("");
     }
  }

  /**
   * Invoked for a directory before entries in the
   * directory are visited.
   */
  @Override
  public FileVisitResult preVisitDirectory(
           Path dir,
           BasicFileAttributes attrs) throws IOException
  {
      //printBklanklines(1);
//      msg = String.format("in --> We're just about to look in directory %s%n",
//                 dir.getFileName().toString());
      msg = String.format("in --> We're just about to look in directory %s%n",
                 dir.toAbsolutePath().toString());
      System.out.println(msg);
      append2Pathtaken(msg);
      //append2Pathtaken(msg);

      //resetFileCount();
      return CONTINUE;
  }// end of preVisitDirectory

  /**
   * Invoked for a file in a directory.
   */
  @Override
  public FileVisitResult visitFile(
           Path file,
           BasicFileAttributes attrs) throws IOException
  {

      msg = String.format("Looked at file: %s%n", file.getFileName().toString());
      System.out.println(msg);
//      append2Pathtaken(msg);
      //incrementFileCount();

      return CONTINUE;
  }// end of visitFile

  /**
   * Invoked for a directory after entries in the directory,
   * and ALL OF THEIR DESCENDANTS, have been visited.
   */
  @Override
  public FileVisitResult postVisitDirectory(
           Path dir,
           IOException exc) throws IOException
  {

      msg = String.format("out ++> %s done%n", dir.toAbsolutePath().toString());
      System.out.println(msg);
      append2Pathtaken(msg);

      return CONTINUE;
  }// end of postVisitDirectory

  /**
   * Invoked for a file that could not be visited.
   */
  @Override
  public FileVisitResult visitFileFailed(
           Path file,
           IOException exc)
  {
      msg = String.format("Snags with file %s%n", file.getFileName().toString());
      //append2Pathtaken(msg);

      System.err.println(exc);

      return CONTINUE;
  }// end of visitFileFailed

}

// ==============================================
// End of inner class
// ==============================================

}//end of class

I’ve used an inner class for all of the FileVisitor work.

 

See also

Interface java.nio.file.FileVisitor

java.nio.file.SimpleFileVisitor

Advertisements
This entry was posted in java and tagged , . Bookmark the permalink.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s