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