- 浏览: 141864 次
- 性别:
- 来自: 深圳
最新评论
-
freesea:
不错,还没注意java 7已经增加了这么多类了
[NIO.2] 第十篇 NIO.2 中的文件属性 -
SpringJava:
有个问题,想请教一下楼主:在代码中经常看到try catch语 ...
[NIO.2] 第二十九篇 删除、复制、移动目录和文件 -
xiaohu7924:
高
什么是 Java ? -
jiiming:
这种方法可以借鉴
[Java EE 7] Servlet 异步支持 -
cucaracha:
jahu 写道有中文文档没有啊。请留意我的博客:http:// ...
Java EE 7 技术一览
现在,我们编写一个应用来监控 C:\rafaelnadal 目录。此外,如果在这个目录中发生了 CREATE 事件创建了一个新目录,那么这个目录将会被立即注册,和 C:\rafaelnadal 中一开始就存在的目录一样。
首先,创建监控服务:
然后,需要注册目录树的创建、删除和修改事件。稍微麻烦的一点是我们需要注册 C:\rafaelnadal 的所有子目录,而不仅仅只是一个目录。因此需要递归遍历所有子目录,并将其独立注册到监控服务中。要完成这个任务可以使用 SimpleFileVisitor 类,并覆盖 preVisitDirectory 方法,如果你需要处理一些未知的遍历异常,还可以覆盖 visitFileFailed() 方法。接下来,我们按照前面这些描述编写一个方法,名为 registerTree():
如你所见,上面的方法将注册的代码单独放到了 registerPath() 方法中:
现在,所有 C:\rafaelnadal 树下的子目录都注册了新增,修改和删除事件。
接下来,我们需要使用无限循环捕获这些事件。当事件发生后,我们更关注是否是新增事件,如果是新增子目录,那么新增的子目录也需要立即调用 registerTree() 注册到监控服务中。现在有个问题是我们不知道 WatchKey 对应的 Path,因此没办法调用 registerTree() 进行注册。解决办法是将 WatchKey 和对应的 Path 存放到 HashMap 中,在 registerPath() 方法中更新 HashMap 的内容。这样,如果事件发生后,我们就可以直接从 HashMap 中获取 Path 对象:
现在,在无限循环中可以从 HashMap 获取 Path:
HashMap 还可以作为结束无线循环的条件,当 WatchKey 无效时,从 HashMap 中移除,并在 HashMap 为空时跳出循环:
综上所述,编写一个完整的应用:
测试的时候,可以在子目录中创建目录或文件,删除移动目录或文件,观察输出结果。
文章来源:http://www.aptusource.org/2014/04/nio-2-watching-a-directory-tree/
首先,创建监控服务:
private WatchService watchService = FileSystems.getDefault().newWatchService();
然后,需要注册目录树的创建、删除和修改事件。稍微麻烦的一点是我们需要注册 C:\rafaelnadal 的所有子目录,而不仅仅只是一个目录。因此需要递归遍历所有子目录,并将其独立注册到监控服务中。要完成这个任务可以使用 SimpleFileVisitor 类,并覆盖 preVisitDirectory 方法,如果你需要处理一些未知的遍历异常,还可以覆盖 visitFileFailed() 方法。接下来,我们按照前面这些描述编写一个方法,名为 registerTree():
private void registerTree(Path start) throws IOException { Files.walkFileTree(start, new SimpleFileVisitor<Path>() { @Override public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throws IOException { System.out.println("Registering:" + dir); registerPath(dir); return FileVisitResult.CONTINUE; } }); }
如你所见,上面的方法将注册的代码单独放到了 registerPath() 方法中:
private void registerPath(Path path) throws IOException { //register the received path WatchKey key = path.register(watchService, StandardWatchEventKinds.ENTRY_CREATE, StandardWatchEventKinds.ENTRY_MODIFY, StandardWatchEventKinds.ENTRY_DELETE); }
现在,所有 C:\rafaelnadal 树下的子目录都注册了新增,修改和删除事件。
接下来,我们需要使用无限循环捕获这些事件。当事件发生后,我们更关注是否是新增事件,如果是新增子目录,那么新增的子目录也需要立即调用 registerTree() 注册到监控服务中。现在有个问题是我们不知道 WatchKey 对应的 Path,因此没办法调用 registerTree() 进行注册。解决办法是将 WatchKey 和对应的 Path 存放到 HashMap 中,在 registerPath() 方法中更新 HashMap 的内容。这样,如果事件发生后,我们就可以直接从 HashMap 中获取 Path 对象:
private final Map<WatchKey, Path> directories = new HashMap<>(); … private void registerPath(Path path) throws IOException { //register the received path WatchKey key = path.register(watchService, StandardWatchEventKinds.ENTRY_CREATE, StandardWatchEventKinds.ENTRY_MODIFY, StandardWatchEventKinds.ENTRY_DELETE); //store the key and path directories.put(key, path); }
现在,在无限循环中可以从 HashMap 获取 Path:
… while (true) { … if (kind == StandardWatchEventKinds.ENTRY_CREATE) { final Path directory_path = directories.get(key); final Path child = directory_path.resolve(filename); if (Files.isDirectory(child, LinkOption.NOFOLLOW_LINKS)) { registerTree(child); } } … } …
HashMap 还可以作为结束无线循环的条件,当 WatchKey 无效时,从 HashMap 中移除,并在 HashMap 为空时跳出循环:
… while (true) { … //reset the key boolean valid = key.reset(); //remove the key if it is not valid if (!valid) { directories.remove(key); if (directories.isEmpty()) { break; } } } …
综上所述,编写一个完整的应用:
import java.io.IOException; import java.nio.file.FileSystems; import java.nio.file.FileVisitResult; import java.nio.file.Files; import java.nio.file.LinkOption; import java.nio.file.Path; import java.nio.file.Paths; import java.nio.file.SimpleFileVisitor; import java.nio.file.StandardWatchEventKinds; import java.nio.file.WatchEvent; import java.nio.file.WatchEvent.Kind; import java.nio.file.WatchKey; import java.nio.file.WatchService; import java.nio.file.attribute.BasicFileAttributes; import java.util.HashMap; import java.util.Map; class WatchRecursiveRafaelNadal { private WatchService watchService; private final Map<WatchKey, Path> directories = new HashMap<>(); private void registerPath(Path path) throws IOException { //register the received path WatchKey key = path.register(watchService, StandardWatchEventKinds.ENTRY_CREATE, StandardWatchEventKinds.ENTRY_MODIFY, StandardWatchEventKinds.ENTRY_DELETE); //store the key and path directories.put(key, path); } private void registerTree(Path start) throws IOException { Files.walkFileTree(start, new SimpleFileVisitor<Path>() { @Override public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throws IOException { System.out.println("Registering:" + dir); registerPath(dir); return FileVisitResult.CONTINUE; } }); } public void watchRNDir(Path start) throws IOException, InterruptedException { watchService = FileSystems.getDefault().newWatchService(); registerTree(start); //start an infinite loop while (true) { //retrieve and remove the next watch key final WatchKey key = watchService.take(); //get list of events for the watch key for (WatchEvent<?> watchEvent : key.pollEvents()) { //get the kind of event (create, modify, delete) final Kind<?> kind = watchEvent.kind(); //get the filename for the event final WatchEvent<Path> watchEventPath = (WatchEvent<Path>) watchEvent; final Path filename = watchEventPath.context(); //handle OVERFLOW event if (kind == StandardWatchEventKinds.OVERFLOW) { continue; } //handle CREATE event if (kind == StandardWatchEventKinds.ENTRY_CREATE) { final Path directory_path = directories.get(key); final Path child = directory_path.resolve(filename); if (Files.isDirectory(child, LinkOption.NOFOLLOW_LINKS)) { registerTree(child); } } //print it out System.out.println(kind + " -> " + filename); } //reset the key boolean valid = key.reset(); //remove the key if it is not valid if (!valid) { directories.remove(key); //there are no more keys registered if (directories.isEmpty()) { break; } } } watchService.close(); } } public class Main { public static void main(String[] args) { final Path path = Paths.get("C:/rafaelnadal"); WatchRecursiveRafaelNadal watch = new WatchRecursiveRafaelNadal(); try { watch.watchRNDir(path); } catch (IOException | InterruptedException ex) { System.err.println(ex); } } }
测试的时候,可以在子目录中创建目录或文件,删除移动目录或文件,观察输出结果。
文章来源:http://www.aptusource.org/2014/04/nio-2-watching-a-directory-tree/
发表评论
-
[NIO.2] 第四十一篇 随机访问文件概述
2014-04-29 14:51 1825我们已经看过很多顺序读取文件的例子,文件除了可以被顺序读取,还 ... -
[NIO.2] 第三十九篇 实现文件监控服务
2014-04-26 16:13 3714要实现监控服务需要有几个步骤。在本文中,你将会看到实现监控服务 ... -
[NIO.2] 第三十八篇 监控服务 API
2014-04-21 14:13 2052Java 7 NIO.2 引入了线程安全的监控服务,用于监控对 ... -
[NIO.2] 第三十七篇 编写一个文件移动应用
2014-04-18 14:20 1376移动文件分为两个步骤,先拷贝文件,再删除源文件。 下面的代码 ... -
[NIO.2] 第三十六篇 编写一个文件拷贝应用
2014-04-18 14:18 1491拷贝目录树的时候,需要为文件和目录递归调用 Files.cop ... -
[NIO.2] 第三十五篇 编写一个文件删除应用
2014-04-17 18:22 1894如果要删除单个文件,可以直接调用 delete() 或 del ... -
[NIO.2] 第三十四篇 编写一个文件搜索应用
2014-04-14 15:39 1511大多数操作系统都提供了独立的工具用于文件搜索(例如,Linux ... -
[NIO.2] 第三十三篇 遍历目录树
2014-04-14 15:35 2453一旦你创建了遍历机制(实现 FileVisitor 接口或继承 ... -
[NIO.2] 第三十二篇 SimpleFileVisitor 类
2014-04-12 15:57 2074要实现 FileVisitor 接口就要实现接口上的所有方法, ... -
[NIO.2] 第三十一篇 FileVisitor 接口
2014-04-12 15:53 3262FileVisitor 接口提供了递归遍历文件树的支持。这个接 ... -
[NIO.2] 第三十篇 递归操作简述
2014-04-12 15:46 1094你可能知道,在编程中使用递归技术一直有争议,但是它的确简化了一 ... -
[NIO.2] 第二十九篇 删除、复制、移动目录和文件
2014-04-10 16:28 5400删除、拷贝和移动操作是最常见的文件操作。NIO.2 提供了独立 ... -
[NIO.2] 第二十八篇 创建临时目录和文件
2014-04-09 13:59 4575临时目录是用于存储临时文件的目录。临时目录的位置依赖操作系统。 ... -
[NIO.2] 第二十七篇 新建、读取和写出文件
2014-04-07 20:09 4235对文件来说,可能最常用的操作就是创建、读取和写出。NIO.2 ... -
[NIO.2] 第二十六篇 创建目录以及列出目录内容
2014-04-07 12:14 2541列出文件系统根目录 在 Java 6 中,获取根目录是通过 ... -
[NIO.2] 第二十五篇 文件及目录的校验
2014-04-05 16:26 1921在对文件或目录进行操 ... -
[NIO.2] 第二十四篇 定位链接所指向的目标文件位置
2014-04-03 18:30 1075调用 Files.readSymbolicLink() 方法可 ... -
[NIO.2] 第二十三篇 检验软链接
2014-04-03 12:12 1785Path 对象可能表示文件或链接。如果 Path 对象指向软链 ... -
[NIO.2] 第二十二篇 创建硬链接
2014-04-03 00:11 1927可以调用 createLink() 方法创建硬链接,它将会创建 ... -
[NIO.2] 第二十一篇 创建软链接
2014-04-02 18:35 3282在 NIO.2 中,创建软链接非常简单,只需要调用 Files ...
相关推荐
BoneCP很小,只有四十几K(运行时需要slf4j和guava的支持,这二者加起来就不小了),而相比之下 C3P0 要六百多K。 异步输出框架 AsynWriter 一个Java的类库,用于异步输出记录的简单小框架用于高并发下数据输出使用...
BoneCP很小,只有四十几K(运行时需要slf4j和guava的支持,这二者加起来就不小了),而相比之下 C3P0 要六百多K。 异步输出框架 AsynWriter 一个Java的类库,用于异步输出记录的简单小框架用于高并发下数据输出使用...
BoneCP很小,只有四十几K(运行时需要slf4j和guava的支持,这二者加起来就不小了),而相比之下 C3P0 要六百多K。 异步输出框架 AsynWriter 一个Java的类库,用于异步输出记录的简单小框架用于高并发下数据输出使用...
BoneCP很小,只有四十几K(运行时需要slf4j和guava的支持,这二者加起来就不小了),而相比之下 C3P0 要六百多K。 异步输出框架 AsynWriter 一个Java的类库,用于异步输出记录的简单小框架用于高并发下数据输出使用...
BoneCP很小,只有四十几K(运行时需要slf4j和guava的支持,这二者加起来就不小了),而相比之下 C3P0 要六百多K。 异步输出框架 AsynWriter 一个Java的类库,用于异步输出记录的简单小框架用于高并发下数据输出使用...
BoneCP很小,只有四十几K(运行时需要slf4j和guava的支持,这二者加起来就不小了),而相比之下 C3P0 要六百多K。 异步输出框架 AsynWriter 一个Java的类库,用于异步输出记录的简单小框架用于高并发下数据输出使用...
BoneCP很小,只有四十几K(运行时需要slf4j和guava的支持,这二者加起来就不小了),而相比之下 C3P0 要六百多K。 异步输出框架 AsynWriter 一个Java的类库,用于异步输出记录的简单小框架用于高并发下数据输出使用...
BoneCP很小,只有四十几K(运行时需要slf4j和guava的支持,这二者加起来就不小了),而相比之下 C3P0 要六百多K。 异步输出框架 AsynWriter 一个Java的类库,用于异步输出记录的简单小框架用于高并发下数据输出使用...
BoneCP很小,只有四十几K(运行时需要slf4j和guava的支持,这二者加起来就不小了),而相比之下 C3P0 要六百多K。 异步输出框架 AsynWriter 一个Java的类库,用于异步输出记录的简单小框架用于高并发下数据输出使用...
BoneCP很小,只有四十几K(运行时需要slf4j和guava的支持,这二者加起来就不小了),而相比之下 C3P0 要六百多K。 异步输出框架 AsynWriter 一个Java的类库,用于异步输出记录的简单小框架用于高并发下数据输出使用...
BoneCP很小,只有四十几K(运行时需要slf4j和guava的支持,这二者加起来就不小了),而相比之下 C3P0 要六百多K。 异步输出框架 AsynWriter 一个Java的类库,用于异步输出记录的简单小框架用于高并发下数据输出使用...