Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java 7 walkFileTree calling visitFile on directories

Tags:

java-7

nio2

Say I have the following directory structure

/root/dir
/root/dir/file1.txt
/root/dir/subdir
/root/dir/subdir/file2.txt

And let's say I'll be using the following visitor:

class MyFileVisitor extends SimpleFileVisitor<Path> {

  @Override
  public FileVisitResult visitFile(final Path file, final BasicFileAttributes attrs)
  throws IOException {
    if(Files.isDirectory(file)) {
      throw new IllegalStateException("WAT!? Visiting directory: "+file.toAbsolutePath().toString());
    }
    System.out.println("Visiting file: "+file.toAbsolutePath().toString());
    return super.visitFile(file, attrs);
  }

If we use the simple overload of walkFileTree:

Files.walkFileTree(Paths.get("/root/dir"), new MyFileVisitor());  

Everything goes according to plan and we see the following output:

Visiting file: /root/dir/file1.txt
Visiting file: /root/dir/subdir/file2.txt

But when we try setting the max depth, things start to break down:

Files.walkFileTree(Paths.get("/root/dir"), EnumSet.noneOf(FileVisitOption.class), 1, new MyFileVisitor());

Output:

Visiting file: /root/dir/file1.txt

java.lang.IllegalStateException: WAT!? Visting directory: /root/dir/subdir

I'm pretty sure this is a bug, but I wanted to ask the community first: Is there something I'm missing and this is actually expected behavior? Thanks for confirming!

Details:

java -version
java version "1.7.0_45"
Java(TM) SE Runtime Environment (build 1.7.0_45-b18)
Java HotSpot(TM) 64-Bit Server VM (build 24.45-b08, mixed mode)
like image 701
Matthew Madson Avatar asked Nov 02 '25 05:11

Matthew Madson


1 Answers

I played around a little bit with your code and added a couple of lines:

/*
 * (non-Javadoc)
 * 
 * @see java.nio.file.SimpleFileVisitor#preVisitDirectory(java.lang.Object,
 * java.nio.file.attribute.BasicFileAttributes)
 */
@Override
public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs)
        throws IOException {
    System.out.println(Thread.currentThread().getStackTrace()[1] + " "
            + dir);
    return super.preVisitDirectory(dir, attrs);
}

/*
 * (non-Javadoc)
 * 
 * @see java.nio.file.SimpleFileVisitor#postVisitDirectory(java.lang.Object,
 * java.io.IOException)
 */
@Override
public FileVisitResult postVisitDirectory(Path dir, IOException exc)
        throws IOException {
    System.out.println(Thread.currentThread().getStackTrace()[1] + " "
            + dir);
    return super.postVisitDirectory(dir, exc);
}

/*
 * (non-Javadoc)
 * 
 * @see java.nio.file.SimpleFileVisitor#visitFileFailed(java.lang.Object,
 * java.io.IOException)
 */
@Override
public FileVisitResult visitFileFailed(Path file, IOException exc)
        throws IOException {
    System.out.println(Thread.currentThread().getStackTrace()[1] + " "
            + file);
    return super.visitFileFailed(file, exc);
}

just no-brainers to see what's going on.

What you call a bug happens here java.nio.file.FileTreeWalker:134:

    // at maximum depth or file is not a directory
    if (depth >= maxDepth || !attrs.isDirectory()) {
        return visitor.visitFile(file, attrs);
    }

Finally, what I think about it:

1.: subdir is part of depth 1
2.: Without the visitFile for deepest directories, you wouldn't even recognize they are there.

So I think that's regular behaviour.

By the way, you could use the attrs in your override of:

@Override
public FileVisitResult visitFile(final Path file,
        final BasicFileAttributes attrs) throws IOException {
    if (attrs.isDirectory()) {
        throw new IllegalStateException("WAT!? Visiting directory: "
                + file.toAbsolutePath().toString());
    }
    System.out
            .println("Visiting file: " + file.toAbsolutePath().toString());
    return super.visitFile(file, attrs);
}
like image 133
Franz Ebner Avatar answered Nov 04 '25 10:11

Franz Ebner



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!