首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Java 7 walkFileTree在目录上调用visitFile

Java 7 walkFileTree在目录上调用visitFile
EN

Stack Overflow用户
提问于 2013-12-19 07:51:27
回答 3查看 5.5K关注 0票数 3

假设我有以下目录结构

代码语言:javascript
复制
/root/dir
/root/dir/file1.txt
/root/dir/subdir
/root/dir/subdir/file2.txt

假设我将使用以下访问者:

代码语言:javascript
复制
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);
  }

如果我们使用walkFileTree的简单重载:

代码语言:javascript
复制
Files.walkFileTree(Paths.get("/root/dir"), new MyFileVisitor());  

一切按计划进行,我们看到以下输出:

代码语言:javascript
复制
Visiting file: /root/dir/file1.txt
Visiting file: /root/dir/subdir/file2.txt

但是当我们尝试设置最大深度时,事情就开始崩溃了:

代码语言:javascript
复制
Files.walkFileTree(Paths.get("/root/dir"), EnumSet.noneOf(FileVisitOption.class), 1, new MyFileVisitor());

输出:

代码语言:javascript
复制
Visiting file: /root/dir/file1.txt

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

我很确定这是一个bug,但我想首先问社区:我是否遗漏了什么,这实际上是预期的行为吗?谢谢你的确认!

详细信息:

代码语言:javascript
复制
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)
EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2014-01-02 20:19:59

我玩了一下你的代码,并添加了几行代码:

代码语言:javascript
复制
/*
 * (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);
}

只是没脑子看看到底怎么回事。

你所说的bug发生在这里,java.nio.file.FileTreeWalker:134

代码语言:javascript
复制
    // at maximum depth or file is not a directory
    if (depth >= maxDepth || !attrs.isDirectory()) {
        return visitor.visitFile(file, attrs);
    }

最后,我的想法是:

1.:subdir是深度1的一部分

2.:如果没有用于最深目录的visitFile,您甚至都不会认识到它们在那里。

所以我认为这是正规行为

顺便说一句,您可以在覆盖以下内容时使用attrs:

代码语言:javascript
复制
@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);
}
票数 5
EN

Stack Overflow用户

发布于 2018-12-14 11:18:28

我真的相信

java.nio.file.Files#walkFileTree(java.nio.file.Path, java.util.Set, int, java.nio.file.FileVisitor)

破坏了java.nio.file.FileVisitor接口的契约。

简单地说,visitFile方法是在目录上调用的,如果它们恰好在所提供的深度级别上的话,它们也是

如果您阅读接口java.nio.file.FileVisitor#visitFile的文档,这实际上是没有意义的,它明确指出:

为目录中的文件调用。

示例:

给定以下文件系统结构:

代码语言:javascript
复制
───start_dir
   │   file1.txt
   │
   ├───dir1
   │       file11.txt
   │
   └───dir2
       └───dir21
               file211.txt

调用walkFileTree按预期在足够大的深度中工作

代码语言:javascript
复制
Files.walkFileTree(Paths.get("start_dir"), 
                   EnumSet.noneOf(FileVisitOption.class),
                   1000, 
                   new MyFileVisitor());

生成与接口一致的下列调用:

代码语言:javascript
复制
Previsit  dir: start_dir
Previsit  dir: start_dir\dir1
Visit    file: start_dir\dir1\file11.txt
Postvisit dir: start_dir\dir1
Previsit  dir: start_dir\dir2
Previsit  dir: start_dir\dir2\dir21
Visit    file: start_dir\dir2\dir21\file211.txt
Postvisit dir: start_dir\dir2\dir21
Postvisit dir: start_dir\dir2
Visit    file: start_dir\file1.txt
Postvisit dir: start_dir

用walkFileTree深度1调用

代码语言:javascript
复制
Files.walkFileTree(Paths.get("start_dir"),
                   EnumSet.noneOf(FileVisitOption.class),
                   1, 
                   new MyFileVisitor());

生成以下调用,其中除文件外,还在第一级目录上调用visitFile:

代码语言:javascript
复制
Previsit  dir: start_dir
Visit    file: start_dir\dir1
Visit    file: start_dir\dir2
Visit    file: start_dir\file1.txt
Postvisit dir: start_dir

用walkFileTree深度2调用

代码语言:javascript
复制
Files.walkFileTree(Paths.get("start_dir"), 
                   EnumSet.noneOf(FileVisitOption.class),
                   2, 
                   new MyFileVisitor());

生成以下调用,其中visitFile是,而不是在第一级目录上调用的,而是在第二级目录上调用的:

代码语言:javascript
复制
Previsit  dir: start_dir
Previsit  dir: start_dir\dir1
Visit    file: start_dir\dir1\file11.txt
Postvisit dir: start_dir\dir1
Previsit  dir: start_dir\dir2
Visit    file: start_dir\dir2\dir21
Postvisit dir: start_dir\dir2
Visit    file: start_dir\file1.txt
Postvisit dir: start_dir
票数 4
EN

Stack Overflow用户

发布于 2019-10-27 19:45:41

此行为是在文件文档::演练文件树中指定的,因此它是有意的,而不是bug:

对在visitFile中遇到的所有文件(包括目录)调用maxDepth方法。

为了防止在目录上调用visitFile,目录在整个java.nio.file类的文档中被隐式调用。例如,Files::walkFileTree的文档本身说,“该方法遍历根植于给定起始文件的文件树”,并且“启动文件”(当然)可能是一个目录

还请注意,也可以在目录上调用visitFileFailed,如文档中所解释的那样:

如果该文件是一个目录,并且无法打开该目录,则调用visitFileFailed方法时会出现I/O异常。

Franz展示了发生这种行为的代码,我同意他为什么认为这是故意的:“如果没有最深目录的visitFile,您甚至都不会认识到它们在那里。”如果只需要常规文件(或符号链接),我也同意使用attrs参数检查文件类型。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/20676146

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档