fscmonitor这个程序是监控某个目录文件变化,记录到文本中。根据当前的日期,把变化的内容记录到文本中,一天的内容会记录到同一个文件中。内容由时间,类型和文件路径组成。
1624237980272---ENTRY_MODIFY---d:\temp\20190219102905926.png
主要程序如下:
private final Map<WatchKey, Path> keys;
private final Map<Path, Path> dirkeys;
private int deltype = PropertiesUtils.getIntValue(Content.ONDELETE);
FileMonitor(Path dir) throws IOException {
this.watcher = FileSystems.getDefault().newWatchService();
this.keys = new HashMap<WatchKey, Path>();
this.dirkeys = new HashMap<Path, Path>();
walkAndRegisterDirectories(dir);
}
private void registerDirectory(Path dir) throws IOException {
WatchKey key = dir.register(watcher, ENTRY_CREATE, ENTRY_DELETE,
ENTRY_MODIFY);
keys.put(key, dir);
dirkeys.put(dir, dir);
}
private void walkAndRegisterDirectories(final Path start)
throws IOException {
Files.walkFileTree(start, new SimpleFileVisitor<Path>() {
@Override
public FileVisitResult preVisitDirectory(Path dir,
BasicFileAttributes attrs) throws IOException {
registerDirectory(dir);
return FileVisitResult.CONTINUE;
}
});
}
void processEvents() throws IOException {
for (; ; ) {
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()) {
@SuppressWarnings("rawtypes")
WatchEvent.Kind kind = event.kind();
@SuppressWarnings("unchecked")
Path name = ((WatchEvent<Path>) event).context();
Path child = dir.resolve(name);
logger.info(System.currentTimeMillis() + "---"
+ event.kind().name() + "---" + child);
if (kind == ENTRY_CREATE) {
if (Files.isDirectory(child)) {
walkAndRegisterDirectories(child);
}
}
if (kind == ENTRY_MODIFY) {
Path dirchild = dirkeys.get(child);
if (dirchild == null) {
FileOper.write(System.currentTimeMillis() + "---"
+ event.kind().name() + "---" + child + "\r\n");
}
}
if (kind == ENTRY_DELETE) {
if(deltype == 1) {
Path dirchild = dirkeys.get(child);
if (dirchild == null) {
FileOper.write(System.currentTimeMillis() + "---"
+ event.kind().name() + "---" + child + "\r\n");
} else {
dirkeys.remove(child);
}
}
}
}
boolean valid = key.reset();
if (!valid) {
keys.remove(key);
if (keys.isEmpty()) {
break;
}
}
}
}
ENTRY_CREATE这种是创建文件类型,由于生成一个文件先创建然后ENTRY_MODIFY,所以创建类型就不记录。ENTRY_MODIFY类型可能会触发多次,ENTRY_DELETE类型的根据配置来决定是否记录,因为有些情况只是进行备份怕丢失,如果人为的进行删除,可能就造成删除同步,备份也会被删除。
还有对外的接口,需要在head中传入Authorization,默认用户和密码都是root。由于如果在程序未启动的时候是记录不了文件的变化,就有可能造成遗漏,可以进行全量的查询。
createfileall接口就是全量文件生成名字为20000101的一个文件。fileall接口是以json格式返回全量的文件信息。filebyfold接口是以json格式返回某个文件夹的文件信息。
配置
monitor.monitoraddress:监控的目录
monitor.address:生成文本的目录
monitor.port:http端口
monitor.ondelet:是否生成删除记录
monitor.author:http的Authorization
打包把fscmonitor文件夹打包成一个可执行的jar,main是FileMonitor,config.properties配置文件放到和jar同一个目录。main内容如下
public static void main(String[] args) throws Exception {
MonitorServer ms = new MonitorServer();
ms.start();
Path dir = Paths.get(PropertiesUtils.getStringValue(Content.MONITOR_ADDRESS));
new FileMonitor(dir).processEvents();
}
具体代码详见
Github地址 https://github.com/zzxiaoma163/fsc
gitee地址 https://gitee.com/XiaoMaGeGeW/fsc