基于JDK7,监控某文件夹拷贝文件,监控本身很简单用WatcherService实现,主要是如何确定文件拷贝完成,这里使用移动文件的思路
import org.apache.commons.io.FileUtils; import org.joda.time.DateTime; import org.joda.time.format.DateTimeFormat; import org.joda.time.format.DateTimeFormatter; import java.io.File; import java.io.IOException; import java.nio.file.*; import java.util.UUID; import static java.nio.file.StandardWatchEventKinds.*; /** * JDK7 NIO2 文件监控 */ public class MyWatcherService { // 时间格式化Format private static final DateTimeFormatter dirNameFormat = DateTimeFormat.forPattern("yyyy-MM-dd HH mm ss "); public static void main(String[] args) throws IOException, InterruptedException { String dir = "C:\\Users\\Administrator\\Desktop\\test"; Path path = Paths.get(dir); WatchService watcher = FileSystems.getDefault().newWatchService(); path.register(watcher, ENTRY_CREATE, ENTRY_DELETE, ENTRY_MODIFY); while (true) { /** * 拷贝文件会触发 一次ENTRY_CREATE 两次ENTRY_MODIFY(文件可能只触发一次ENTRY_MODIFY) * 拷贝文件会触发 一次ENTRY_CREATE 两次ENTRY_MODIFY 一次ENTRY_DELETE * 删除文件会触发 一次ENTRY_DELETE */ WatchKey key = watcher.take(); for (WatchEvent<?> event : key.pollEvents()) { WatchEvent.Kind kind = event.kind(); if (kind == OVERFLOW) {//事件可能lost or discarded System.out.println("事件可能lost or discarded"); continue; } WatchEvent<Path> e = (WatchEvent<Path>) event; String kindName = kind.name(); Path fileName = e.context(); System.out.printf("Event %s has happened,which fileName is %s%n", kindName, fileName); if ("ENTRY_MODIFY".equals(kindName)) { rename(dir, fileName.toString()); } } // 重置 key 如果失败结束监控 if (!key.reset()) { break; } } } /** * 通过修改文件名判断文件拷贝完成 */ public static void rename(String dir, String fileName) { File src = new File(dir + File.separator + fileName); String tmp = "C:\\Users\\Administrator\\Desktop\\test2"; File dest = new File(tmp + File.separator + DateTime.now().toString(dirNameFormat) + UUID.randomUUID().toString().replaceAll("-", "") + File.separator + fileName); try { // 未拷贝完成移动失败 FileUtils.moveFile(src, dest); } catch (Exception e) { FileUtils.deleteQuietly(dest.getParentFile()); } if (dest.exists()) { System.out.printf("file %s copy over , you can do next with %s%n", src.getAbsolutePath(), dest.getAbsolutePath()); } } }
完善版本
使用中发现,如果一次导入大量数据会存在有些event来不及处理就过去的情况,从结果来看就是文件夹中留存一些文件没有处理,进一步的解决方法是采用阻塞队列,文件监控进程只负责把文件名放到队列中
1.主程序启动一个文件监控进程,一个文件处理进程
import java.util.concurrent.BlockingQueue; import java.util.concurrent.LinkedBlockingQueue; /** * <pre> * 功能说明:启动两个线程一个监控文件夹改变 一个处理文件 * </pre> */ public class MyWatcherService2 { public static void main(String[] args) { // 创建单向队列queue DirWatch进程将监控到的文件放到队列中 Processor检查处理队列中的文件 BlockingQueue<String> queue = new LinkedBlockingQueue<String>(); DirWatch watch = new DirWatch(queue); Thread watchThread = new Thread(watch); watchThread.start(); Processor processor = new Processor(queue); Thread processorThread = new Thread(processor); processorThread.start(); while (true) { try { Thread.sleep(9999999); } catch (InterruptedException e) { e.printStackTrace(); } } } }
2.文件监控进程
import java.nio.file.*; import java.util.concurrent.BlockingQueue; import static java.nio.file.StandardWatchEventKinds.*; /** * <pre> * 功能说明:通过NIO 监控文件夹并放入队列中 * </pre> */ public class DirWatch implements Runnable { private BlockingQueue<String> queue; public DirWatch(BlockingQueue<String> queue) { this.queue = queue; } @Override public void run() { String sourceDir = "D:\\bigdata\\src"; try { // 对文件夹进行监控 Path path = Paths.get(sourceDir); WatchService watcher = FileSystems.getDefault().newWatchService(); path.register(watcher, ENTRY_CREATE, ENTRY_DELETE, ENTRY_MODIFY); while (true) { WatchKey key = watcher.take(); for (WatchEvent<?> event : key.pollEvents()) { WatchEvent.Kind kind = event.kind(); if (kind == OVERFLOW) { System.out.println("事件可能lost or discarded"); continue; } WatchEvent<Path> e = (WatchEvent<Path>) event; String kindName = kind.name(); Path fileName = e.context(); // System.out.printf("Event %s has happened,which fileName is %s%n", kindName, fileName); if ("ENTRY_MODIFY".equals(kindName)) { // 放到队列中 如果队列满抛出异常 证明程序逻辑出现问题 理论上不可能满 queue.add(fileName.toString()); } } // 重置 key 如果失败结束监控 if (!key.reset()) { throw new RuntimeException("重置Key失败,结束监控"); // break; } } } catch (Exception e) { System.out.println("监控异常, 停止程序"); // 无法处理QAR数据 结束程序 System.exit(1); } } }
3.文件处理进程
import org.apache.commons.io.FileUtils; import org.joda.time.DateTime; import org.joda.time.format.DateTimeFormat; import org.joda.time.format.DateTimeFormatter; import java.io.File; import java.util.UUID; import java.util.concurrent.BlockingQueue; /** * <pre> * 功能说明:通过移动文件的方法判断文件拷贝完成 并处理文件 * </pre> */ public class Processor implements Runnable { // 时间格式化Format private DateTimeFormatter dirNameFormat = DateTimeFormat.forPattern("yyyy-MM-dd HH mm ss "); private BlockingQueue<String> queue; public Processor(BlockingQueue<String> queue) { this.queue = queue; } @Override public void run() { String sourceDir = "D:\\bigdata\\src"; String resDir = "D:\\bigdata\\res"; try { while (true) { String fileName = queue.take(); File src = new File(sourceDir + File.separator + fileName); // 再一次移动防止提交重名文件覆盖正在处理的文件 File dest = new File(resDir + File.separator + DateTime.now().toString(dirNameFormat) + UUID.randomUUID().toString().replaceAll("-", "") + File.separator + fileName); try { // 未拷贝完成不能移动 FileUtils.moveFile(src, dest); } catch (Exception e) { // 删除建立的空目录 FileUtils.deleteQuietly(dest.getParentFile()); } if (dest.exists()) { try { System.out.printf("file %s copy over , you can do next with %s%n", src.getAbsolutePath(), dest.getAbsolutePath()); } catch (Exception e) { e.printStackTrace(); } } } } catch (Exception e) { System.out.println("处理异常, 停止程序"); // 无法处理QAR数据 结束程序 System.exit(1); } } }
相关推荐
使用jdk7的NIO2进行文件或文件夹的拷贝移动操作。可以自动创建路径,差异化更新文件,简单的出错重连机制
JDK1.7新特性,NIO2异步学习笔记。
NULL 博文链接:https://xxing22657-yahoo-com-cn.iteye.com/blog/1054496
jdk7 原生的监控包含很多编程细节, 实际工作不得不处理这些复杂的细节,这里进行轻量封装 提取出fileCreated,fileModified,fileDeleted,fileRenamed等更好用的接口
本类,是专门为了处理大文件,按行读取开发的类。 采用读文件的缓存 fbb 1024*5 行缓存 bb 256 字节 设计思想: 每次通过nio读取字节到 fbb中 然后对fbb自己中的内容进行行判断即 10 回车 13 行号 0 文件...
从oracle官网下载,现在oracle官网下载jdk要求注册账号。防止麻烦特意上传
jdk1.7的文件夹形式,解压之后,手动配置环境变量,亲测有效
1.4 JDK7新特性<四> NIO2.0 文件系统 . . . 1.5 JDK7新特性<五> fork/join 框架 . . . . . 1.6 JDK7新特性<六> 监听文件系统的更改 1.7 JDK7新特性<七> 遍历文件树 . . . . . . . 1.8 JDK7新特性<八>异步io/AIO ...
屏蔽jdk7文件监控细节,提取fileCreated,fileModified,fileDeleted,fileRenamed等方法,API更简洁、好用
JDK路径下各个文件夹的作用.pdf
jdk1.6 源码 包含nio等 jdk1.6 源码 包含nio等 jdk1.6 源码 包含nio等
jdk7 安装文件 系统
本地开发调试环境安装jdk版本对应jdk_7及jdk_8,并顺带将windows环境变量配置、查看安装版本指令。
最常用和实用的JDK内存和线程监控指令,堆栈监控指令及操作步骤
jdk7的32位分享,其他版本的和64位的可以见【https://blog.csdn.net/qq_27471405/article/details/82635077】此文章下载,还有为什么积分不能选择0,为什么不能免费分享 给大家呢
jdk7 jdk8 jdk9 jdk10 jdk11 jdk12 jdk13 jdk14 (win-64位) 资源共享
jdk7j下载jdk7j下载jdk7j下载jdk7j下载jdk7j下载jdk7j下载jdk7j下载jdk7j下载jdk7j下载jdk7j下载jdk7j下载jdk7j下载jdk7j下载
主要是一些关于NIO2的基本操作和内容,内容是网上下载的收集的,适合没有使用过JDK7以上版本或没有使用过新的文件操作的规范的新手。
jdk 1.7 mac版本,dmp文件,网盘链接地址!网盘链接地址!网盘链接地址!
jdk7 64位绿色免安装版本,因为csdn上传的文件不能大于60M,所以分为三部分,下载后解压到同一个文件夹,然后配置环境变量就可以了