`
AsWater
  • 浏览: 24773 次
  • 性别: Icon_minigender_1
  • 来自: 成都
社区版块
存档分类
最新评论

Java SE 7新特性之文件操作(9) - 遍历目录树

阅读更多

转自 开发者的天空

 

在有些时候,我们可能需要遍历整个目录树,例如需要寻找所有的.java文件。Java SE 7提供了很方便的方法来实现这类的功能。
Java SE 7提供的实现这类功能的方法就是FileVisitor接口。FileVisitor接口定义了在遍历中的关键点所需要的行为:当访问文件的时候,在访问 目录前,访问目录后以及出现错误时。对应的这个接口定义了5个方法:

    * preVisitDirectory(T) – 在目录被访问前调用。
    * preVisitDirectoryFailed(T, IOException) – 当目录不能被访问的时候调用。当访问目录发生异常的时候,异常会被传入该方法,我们可以选择怎样处理这些异常,是直接抛出还是仅仅输出到log文件中等 等。
    * postVisitDirectory – Invoked after all the entries in a directory are visited. If any errors are encountered, the specific exception is passed to the method.当一个目录中的所有的内容都被访问之后,该方法会被调用。如果有什么错误发生,那么异常会被传入该方法中。
    * visitFile –  当文件被访问的时候该方法会被调用。文件的基本属性会被传入该方法中,或者我们可以使用文件属性包来获取特殊的属性。例如我们可以读取文件的 DosFileAttributeView来判断文件是否被隐藏了。
    * visitFileFailed –当文件不能访问的时候,该方法会被调用。异常会被传入该方法,我们可以任意选择怎样处理这个异常。

并不是在所有的情况下我们对这5中情况都需要做特殊的处理,为了简化编程,Java SE 7提供了一个缺省的实现SimpleFileVisitor。该类会遍历目录树 ,并抛出所有遇到的异常。我们可以继承该 类,仅仅重写我们需要的实现特殊逻辑的方法。

下面是一个例子,在这个例子中,我们继承了SimplerFileVisitor类。我们要实现的功能是遍历目录树,打印出所有文件/目录的名称和文件大 小。任何碰到的异常都会被输出到控制台中。

    import static java.nio.file.FileVisitResult.*;

    public static class PrintFiles extends SimpleFileVisitor<Path> {

        //Print information about each type of file.
        @Override
        public FileVisitResult visitFile(Path file, BasicFileAttributes attr) {
            if (attr.isSymbolicLink()) {
                System.out.format("Symbolic link: %s ", file);
            } else if (attr.isRegularFile()) {
                System.out.format("Regular file: %s ", file);
            } else {
                System.out.format("Other: %s ", file);
            }
            System.out.println("(" + attr.size() + "bytes)");
            return CONTINUE;
        }

        //Print each directory visited.
        @Override
        public FileVisitResult postVisitDirectory(Path dir, IOException exc) {
            System.out.format("Directory: %s%n", dir);
            return CONTINUE;
        }

        //If there is some error accessing the directory, let the user know.
        //If you don't override this method and an error occurs, an IOException
        //is thrown.
        @Override
        public FileVisitResult preVisitDirectoryFailed(Path dir, IOException exc) {
            System.err.println(exc);
            return CONTINUE;
        }

        //If there is some error accessing the file, let the user know.
        //If you don't override this method and an error occurs, an IOException
        //is thrown.
        @Override
        public FileVisitResult visitFileFailed(Path file, IOException exc) {
            System.err.println(exc);
            return CONTINUE;
        }
    }
 

我 们需要的类已经创建好了,下面我们来看看怎样使用这个类。要遍历一个目录有两个方法可以调用,第一个方法仅仅需要传入目录的起点和FileVisitor 的
实例,如下面的代码所示:

    Path startingDir = ...;
    PrintFiles pf = new PrintFiles();
    Files.walkFileTree(startingDir, pf);
 

第二个方法可以允许我们指定要访问的层数和一组 FileVisitOption作为参数。如果要调用该方法,又想确保整个目录树都被遍历,可以传入Integer.MAX_VALUE作为访问层数的参 数。可以使用的FileVisitOption枚举量有:
    * FOLLOW_LINKS – 表明所有的符号链接都要被解析成它们指向的目的地
    * DETECT_CYCLES – 检测 循环引用。循环引用是由于符号链接使用不恰当引起 的。

下面的代码演示了怎样调用这个方法:

    import static java.nio.file.FileVisitResult.*;

    Path startingDir = ...;

    EnumSet<FileVisitOption> opts = EnumSet.of(FileVisitOption.FOLLOW_LINKS);

    Finder finder = new Finder(pattern);
    Files.walkFileTree(startingDir, opts, Integer.MAX_VALUE, finder);
 

在 遍历目录树的时候是深度优先的。但是在同一级的目录中,我们无法判断哪个会先被访问。如果你的程序要修改文件系统,那么在实现FileVisitor的时 候就需要认真考虑。
例如,如果我们要递归的删除整个目录树,那么我们在删除目录之前要删除其中的所有的文件。我们应该在postVisitDirectory中删除目录本 身。
如果我们是要递归的拷贝整个目录树,我们就需要在preVisitDirectory中创建新的目录,然后在visitFile中拷贝相应的文件。如果要 保持原来目录的属性,那么就在postVisitDirectory中设置新目录的属性。
在遍历目录树的时候,我们还需要决定是否要将符号链接解析为其对应的目的文件/目录。例如我们是要删除目录树,那么就可以不解析符号链接。如果是拷贝目录 树,可能就需要解析。缺省的是不解析的。
在通常情况下只有访问文件时visitFile方法才会被调用。但是,如果我们选择的FOLLOW_LINKS选项并且存在循环链接,那么 visitFile也会被调用,并且该目录会被传入作为参数。因此我们可以使用该特性来判断是否存在循环引用。如:

    public FileVisitResult visitFile(Path file, BasicAttributes attrs) {

        //It's a circular reference!
        if (attrs.isDirectory()) {
            ...
            return CONTINUE;
        }

        //It's a file.
        ...
        return CONTINUE;
    }
 

可 能我们需要的功能是遍历整个目录树来查找特定的目录。当查找到之后就结束。也有可能我们遍历目录树的时候希望跳过某些目录。我们可以通过这些方法的返回值 来控制程序执行的流程。
FileVisitor的这些方法返回FileVisitResult值,我们通过返回不同的值来控制流程。可选的FileVisitResult值有:
    * CONTINUE –表明遍历操作应该继续执行。如preVisitDirectory返回CONTINUE,那么这个目录会被访问。
    * TERMINATE – 立即结束遍历操作。
    * SKIP_SUBTREE – 当preVisitDirectory方法返回这个值的时候,这个目录及其子目录会被跳过。
    * SKIP_SIBLINGS – 当preVisitDirectory方法返回该值的时候,目录不会被访问,postVisitDirectory也不会被调用。其他还没有被访问的兄弟 目录也不会被访问。如果是postVisitDirectory方法返回该值,那么其他没有被访问的兄弟目录不会被访问。

下面的代码中,名为SCCS的目录会被跳过。

    import static java.nio.file.FileVisitResult.*;

    public FileVisitResult preVisitDirectory(Path dir) {
        (if (dir.getName().toString().equals("SCCS")) {
             return SKIP_SUBTREE;
        }
        return CONTINUE;
    }
 

下 面的代码中,一旦特定名称的文件被找到,离开终止遍历操作。

    import static java.nio.file.FileVisitResult.*;

    //The file we are looking for.
    Path lookingFor = ...;

    public FileVisitResult visitFile(Path file, BasicFileAttributes attr) {
        if (file.getName().equals(lookingFor)) {
            System.out.println("Located file: " + file);
            return TERMINATE;
        }
        return CONTINUE;
    }

 
分享到:
评论
2 楼 passtheball 2010-04-15  
楼主你这个是不是有打广告之嫌,不过你那个论坛看起来实在 是不感恭维啊。界面看起来极为不舒服,虽然用的是成熟的论坛系统,但是怎么看怎么感觉山寨。
1 楼 taoyu3781212 2010-04-15  
新的api,还没用过呢。不知道好不好用

相关推荐

    jdk-7u45-windows-x64.exe Java 1.7.0

    4. **文件系统API(NIO.2)**:提供了一组新的类和接口,用于更高效地处理文件系统操作,比如创建、删除、重命名文件,以及遍历目录。 5. **try-with-resources**:自动关闭资源的语句结构,确保在完成操作后正确...

    OCA Java SE 7 Programmer I Certification Guide

    通过系统地学习以上知识点,考生可以全面掌握 Java SE 7 的基础知识与高级特性,并能够顺利通过 Oracle Certified Associate (OCA) Java SE 7 Programmer I 认证考试。这不仅有助于提升个人的技术能力,也为进一步...

    java se练习代码 Java学习资料

    7. **文件和目录操作**:Java的File类提供了操作文件和目录的方法,例如创建、删除、重命名文件,以及遍历目录。 8. **反射**:Java的反射机制允许在运行时动态地获取类的信息并调用其方法,这对于编写通用代码或...

    Java文件管理器

    首先,Java文件管理器的开发基础是Java标准版(Java SE),它提供了丰富的API用于文件操作。核心知识点包括: 1. **文件I/O操作**:Java的`java.io`包提供了大量的类和接口来处理文件输入输出。例如,`File`类用于...

    jdk-7u51-linux-i586.gz

    3. **文件系统API**:NIO.2提供了新的文件系统API,使得文件操作更加灵活和强大,包括文件路径、遍历目录等功能。 4. **try-with-resources**:这个语法结构允许自动关闭资源,如文件流,避免资源泄露,提高了代码...

    java7解压版

    Java 7,全称为Java SE 7 (Java Platform, Standard Edition 7),是Java编程语言的一个重要版本,由Oracle公司发布。这个版本在2011年推出,引入了许多新特性,增强了性能和开发者的生产力。Java 7解压版是免安装...

    Java-jdk-1.7.0

    文件API的增强是Java 7的一大亮点,NIO.2(New IO 2.0)引入了Path、Files和FileVisitor接口,提供了更强大的文件操作功能,如创建、删除、移动和复制文件,以及遍历目录树。 此外,Java 7对并行流(Fork/Join ...

    传智播客Java_SE基础毕向东老师全程笔记

    根据给定的文件信息,以下是对“传智播客Java_SE基础毕向东老师全程笔记”的详细知识点总结: ### 第一章:编程基础 1. **Java的特性和优势**: - **简单性**:Java设计简洁,易于理解和学习。 - **面向对象**:...

    Java开发环境_Jdk7_32位

    6. **文件系统API增强**:NIO.2(New I/O 2)引入了一组新的文件系统API,提供了更丰富的文件操作功能,如递归删除目录、遍历文件树等。 7. **改进的类型推断**:Java 7的编译器在编译过程中能更准确地推断出方法的...

    jdk-7u40-linux-x64.tar.gz

    4. **文件系统 API(NIO.2)**:提供了一组新的API来处理文件系统操作,如`java.nio.file`包,支持更高级别的文件操作,如遍历目录、监控文件变化等。 5. **尝试-with-resources**:这个新特性允许开发者在一个try...

    mysql-connector-java-5.1.25, mysql 5.7.31亲测有效

    MySQL是世界上最受欢迎的关系型数据库管理系统之一,而MySQL Connector/J则是MySQL与Java应用程序之间的桥梁,它是一个JDBC(Java Database Connectivity)驱动程序,使得Java开发者能够方便地在Java应用中访问和...

    Java 1.7 API 中文 帮助文档

    - **新的文件查找器**:通过`Files.walk()`方法可以轻松地遍历目录树。 - **文件观察者API**:利用`WatchService`接口可以监听文件系统的变更事件。 #### 多线程API扩展 - **`ForkJoinPool`**:一种高效的并行执行...

    java API 1.7

    6. **文件系统API增强**: 引入了`java.nio.file`包,提供了一套新的API来处理文件系统操作,包括遍历目录树、检查文件属性、设置权限等。 7. **动态类型语言支持**: Java 7通过JSR 292(Invokedynamic)增强了对...

    java文件下载

    开发人员应避免路径遍历攻击,只允许访问预定义的文件目录。可以使用相对路径或者配置文件中的绝对路径来指定文件位置。 5. **断点续传** 虽然不是所有Java文件下载实现都会包含这一特性,但断点续传可以让用户在...

    java se的资料。(pdf格式)

    这个资料包提供了全面的Java SE学习资源,涵盖了从基础知识到高级特性的多个方面。以下是根据标题、描述和标签整理出的Java SE相关知识点: 1. **J2SE概述**: Java 2 Platform, Standard Edition (J2SE) 是Java的...

    JavaSE7 API 帮助文档

    9. **文件系统API**:java.nio.file包提供了对文件系统的全面控制,包括创建、删除、重命名文件以及遍历目录等功能。 10. **并发工具更新**:Java 7对java.util.concurrent包进行了增强,例如ForkJoinPool和...

    java1.7API中文版

    这个API文档是开发者理解和使用Java平台标准版(Java SE)7功能的关键工具。以下是Java 1.7 API中的主要知识点: 1. **类型推断(Type Inference)**:Java 7引入了类型推断,使得泛型实例化更加简洁。例如,使用`...

    java api7中文带索引chw版

    2. **NIO.2**:Java 7扩展了非阻塞I/O(New IO)的功能,引入了`java.nio.file`包,提供了一组新的文件系统操作API,包括文件和目录的创建、删除、重命名等,并支持文件的路径操作和遍历。`java.nio.file.Files`类...

Global site tag (gtag.js) - Google Analytics