博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
java 1.7watchservice特性学习 文件变更监控
阅读量:6471 次
发布时间:2019-06-23

本文共 8883 字,大约阅读时间需要 29 分钟。

hot3.png

一、首先概述1.7版本上面的这个java.nio.file.WatchService类

1.1 WatchService 可以干什么?

WatchService可以帮助我们监控一些文件是否做了更改,如果文件做了更改,可以帮助我们去做一些响应,比如,配置文件修改了,那么系统应该重新加载一下配置文件,这样可以将最新的配置加载进来。

 

1.2 完成文件监控一些很重要的类

The watch service exits when either the thread exits or when it is closed (by invoking its closed method。当前启动的线程退出或者调用closed方法关闭的时候,watch service也会推出。

1.2.1 java.nio.file.WatchKey类 

此类代表着一个Object(文件或者文件夹) 注册到WatchService后,返回一个WatchKey类。反应当前所注册的Object状态的类。此类封装了不同事件的状态值,比如,当文件(文件夹)被修改或者被删除或者创建的时候,此类首先产生一个信号量,等待消费者来取并且该WatchKey将会进入到WatchService的队列中。如果WatchKey已经进入到队列当中,但是又有了变化,将不会再次进入到队列当中。

WatchService.take()方法可以取到队列的WatchKey.

1.2.2 java.nio.file.Path类

此类代表文件系统上面的一个文件

1.2.2 java.nio.file.WatchEvent类

此类代表文件的一个具体事件。

WatchEvent

1.3 原理探讨()

To implement this functionality, called file change notification, a program must be able to detect what is happening to the relevant directory on the file system. One way to do so is to poll the file system looking for changes, but this approach is inefficient. It does not scale to applications that have hundreds of open files or directories to monitor.

要做到文件变更提醒功能,有一种办法就是轮询文件系统上面的文件确认是否有变更,但是显然这种做法效率不高。

The java.nio.file package provides a file change notification API, called the Watch Service API. This API enables you to register a directory (or directories) with the watch service. When registering, you tell the service which types of events you are interested in: file creation, file deletion, or file modification. When the service detects an event of interest, it is forwarded to the registered process. The registered process has a thread (or a pool of threads) dedicated to watching for any events it has registered for. When an event comes in, it is handled as needed.

Java WatchService 服务提供API,可以注册你感兴趣的事件,当service 发现注册的事件后,就交给处理线程做处理。

1.4 使用注意事项

1.4.1 收到变更事件时候,是否变更已经完成

当收到一个文件变更事件的时候,并不表示该文件已经变更完毕,有可能还在变更当中。

1.4.2 什么时候使用Watch Service比较好.

The Watch Service API is designed for applications that need to be notified about file change events. It is well suited for any application, like an editor or IDE, that potentially has many open files and needs to ensure that the files are synchronized with the file system. It is also well suited for an application server that watches a directory, perhaps waiting for .jsp or .jar files to drop, in order to deploy them.

This API is not designed for indexing a hard drive. Most file system implementations have native support for file change notification. The Watch Service API takes advantage of this support where available. However, when a file system does not support this mechanism, the Watch Service will poll the file system, waiting for events.

1.5 亲自测试

Oracle 官方给出的例子代码:

package com.hpe.common.audit;/* * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * *   - Redistributions of source code must retain the above copyright *     notice, this list of conditions and the following disclaimer. * *   - Redistributions in binary form must reproduce the above copyright *     notice, this list of conditions and the following disclaimer in the *     documentation and/or other materials provided with the distribution. * *   - Neither the name of Oracle nor the names of its *     contributors may be used to endorse or promote products derived *     from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */import java.nio.file.*;import static java.nio.file.StandardWatchEventKinds.*;import static java.nio.file.LinkOption.*;import java.nio.file.attribute.*;import java.io.*;import java.util.*;/** * Example to watch a directory (or tree) for changes to files. */public class WatchDir {    private final WatchService watcher;    private final Map
keys; private final boolean recursive; private boolean trace = false; @SuppressWarnings("unchecked") static
WatchEvent
cast(WatchEvent
event) { return (WatchEvent
)event; } /** * Register the given directory with the WatchService */ private void register(Path dir) throws IOException { WatchKey key = dir.register(watcher, ENTRY_CREATE, ENTRY_DELETE, ENTRY_MODIFY); if (trace) { Path prev = keys.get(key); if (prev == null) { System.out.format("register: %s\n", dir); } else { if (!dir.equals(prev)) { System.out.format("update: %s -> %s\n", prev, dir); } } } keys.put(key, dir); } /** * Register the given directory, and all its sub-directories, with the * WatchService. */ private void registerAll(final Path start) throws IOException { // register directory and sub-directories Files.walkFileTree(start, new SimpleFileVisitor
() { @Override public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throws IOException { register(dir); return FileVisitResult.CONTINUE; } }); } /** * Creates a WatchService and registers the given directory */ WatchDir(Path dir, boolean recursive) throws IOException { this.watcher = FileSystems.getDefault().newWatchService(); this.keys = new HashMap
(); this.recursive = recursive; if (recursive) { System.out.format("Scanning %s ...\n", dir); registerAll(dir); System.out.println("Done."); } else { register(dir); } // enable trace after initial registration this.trace = true; } /** * Process all events for keys queued to the watcher */ void processEvents() { for (;;) {//这是个死循环 // wait for key to be signalled WatchKey key; try { key = watcher.take(); } catch (InterruptedException x) { return; } Path dir = keys.get(key); if (dir == null) { System.err.println("WatchKey not recognized!!"); continue; } for (WatchEvent
event: key.pollEvents()) { WatchEvent.Kind kind = event.kind(); // TBD - provide example of how OVERFLOW event is handled if (kind == OVERFLOW) { continue; } // Context for directory entry event is the file name of entry WatchEvent
ev = cast(event); Path name = ev.context(); Path child = dir.resolve(name); // print out event System.out.format("%s: %s\n", event.kind().name(), child); // if directory is created, and watching recursively, then // register it and its sub-directories if (recursive && (kind == ENTRY_CREATE)) { try { if (Files.isDirectory(child, NOFOLLOW_LINKS)) { registerAll(child); } } catch (IOException x) { // ignore to keep sample readbale } } } // reset key and remove from set if directory no longer accessible boolean valid = key.reset(); if (!valid) { keys.remove(key); // all directories are inaccessible if (keys.isEmpty()) { break; } } } } static void usage() { System.err.println("usage: java WatchDir [-r] dir"); System.exit(-1); }/****************************************** * 使用方法,可以传入两个参数, * 第一个参数表示是否循环遍历该文件夹(可以不传), * 第二个参数代表要监控的文件路径。 * * @param args * @throws IOException */ public static void main(String[] args) throws IOException { // parse arguments if (args.length == 0 || args.length > 2){ usage(); } boolean recursive = false; int dirArg = 0; if (args[0].equals("-r")) { if (args.length < 2){ usage(); } recursive = true; dirArg++; } // register directory and process its events Path dir = Paths.get(args[dirArg]); new WatchDir(dir, recursive).processEvents(); }}

输出结果:

Scanning E:\work\ftp_file\download ...

Done.
ENTRY_CREATE: E:\work\ftp_file\download\New Text Document.txt
ENTRY_DELETE: E:\work\ftp_file\download\New Text Document.txt
ENTRY_CREATE: E:\work\ftp_file\download\11.txt
ENTRY_MODIFY: E:\work\ftp_file\download\11.txt
ENTRY_MODIFY: E:\work\ftp_file\download\11.txt
 

1.6 其它博文参考

http://codingjunkie.net/java-7-watchservice/

转载于:https://my.oschina.net/u/2308739/blog/688636

你可能感兴趣的文章
【iOS-cocos2d-X 游戏开发之十三】cocos2dx通过Jni调用Android的Java层代码(下)
查看>>
MongoDB的基础使用
查看>>
进程间通信——命名管道
查看>>
LINUX 重定向的知识
查看>>
ssh登陆不需要密码
查看>>
ARP
查看>>
java mkdir()和mkdirs()区别
查看>>
桌面支持--excel自动换行
查看>>
虚拟化--003 vcac licence -成功案例
查看>>
windows server 2003各版本及2008各版本的最大识别内存大小
查看>>
OSChina 周六乱弹 ——揭秘后羿怎么死的
查看>>
centos查找未挂载磁盘格式化并挂载
查看>>
IT人员的职业生涯规划
查看>>
sorry,you must have a tty to run sudo
查看>>
ios开发中使用正则表达式识别处理字符串中的URL
查看>>
项目中的积累,及常见小问题
查看>>
Python类型转换、数值操作(收藏)
查看>>
注释书写格式
查看>>
SQL Server 中 EXEC 与 SP_EXECUTESQL 的区别
查看>>
2013=7=30 自增量的浅谈
查看>>