300字范文,内容丰富有趣,生活中的好帮手!
300字范文 > java7 文件_Java SE 7新特性之文件操作(9) - 遍历目录树

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

时间:2020-03-31 06:40:58

相关推荐

java7 文件_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 {

//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 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;

}

分享到:

-04-13 02:33

浏览 2041

论坛回复 / 浏览 (2 / 3729)

评论

2 楼

passtheball

-04-15

楼主你这个是不是有打广告之嫌,不过你那个论坛看起来实在 是不感恭维啊。界面看起来极为不舒服,虽然用的是成熟的论坛系统,但是怎么看怎么感觉山寨。

1 楼

taoyu3781212

-04-15

新的api,还没用过呢。不知道好不好用

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。