基于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); } } }
相关推荐
标题 "Pure JS (2): 热部署 (利用 JDK 7 NIO 监控文件变化)" 提到了一个关于JavaScript开发的话题,特别是热部署(Hot Deployment)的概念,这是一种在开发过程中无需重启应用就能自动更新代码的技术。...
### JDK 7 NIO2 新特性详解 #### 引言 随着 Java 7 的发布,NIO (New I/O) 接口迎来了重要的更新,即 NIO.2 或称为 MNI (More New I/O)。NIO.2 增强了 Java 1.4 中的 NIO API,为开发人员提供了更为强大的 I/O ...
在Java 7中引入的NIO.2(New IO 2.0)提供了一套全新的文件I/O API,显著地增强了对文件系统操作的支持。在这个示例中,我们将深入探讨如何使用NIO.2进行文件和目录的拷贝与移动操作。 首先,`copeOrMoveFile`方法...
7. **lib**:这个目录包含了JDK的各种库文件,如类库、JVM实现和开发工具所需的资源。 8. **bin**:包含可执行文件,如`java`, `javac`, `jar`等,是开发者最常使用的命令行工具。 9. **db**:可能是一个数据库,...
6. **文件系统API**:JDK 7引入了新的`java.nio.file`包,提供了符合POSIX标准的文件系统API,增强了文件操作的能力,如文件路径、文件属性和文件观察等。 7. **改进的垃圾收集**:JDK 7对垃圾收集器进行了优化,...
jdk7 原生的监控包含很多编程细节, 实际工作不得不处理这些复杂的细节,这里进行轻量封装 提取出fileCreated,fileModified,fileDeleted,fileRenamed等更好用的接口
本类,是专门为了处理大文件,按行读取开发的类。 采用读文件的缓存 fbb 1024*5 行缓存 bb 256 字节 设计思想: 每次通过nio读取字节到 fbb中 然后对fbb自己中的内容进行行判断即 10 回车 13 行号 0 文件...
JDK(Java Development Kit)是Oracle公司提供的用于开发和运行Java应用程序的软件工具包,而JDK 1.7,也被称为Java SE 7(Java Standard Edition 7),是Java语言的一个重要版本。它引入了许多新的特性和改进,以...
7. **文件系统API(NIO.2)** 新的java.nio.file包提供了对文件系统的全面访问,包括文件、目录、符号链接和属性。API的设计更加面向对象,使得文件操作更加简洁和强大。 ### 配置环境变量 要使用这个免安装的JDK...
为了更好地支持现代文件系统的需求,JDK 7引入了新的NIO.2 API(New I/O),该API提供了一种更为灵活的方式来处理文件路径、文件锁定以及异步文件I/O操作。 ##### 2.3 多线程编程增强 JDK 7增加了对Fork/Join框架...
《基于JDK7的FileMonitor:精简版文件监控服务详解》 在Java开发中,对文件系统的实时监控是一项常用且重要的任务。JDK7引入了`WatchService`接口,为开发者提供了一种监听文件系统变化的能力。然而,`WatchService...
学习和理解JDK7的NIO2.0对于提升Java应用的性能和可扩展性至关重要,尤其是在处理大量I/O操作的场景下,如文件服务器、日志系统或者大型数据处理应用。同时,NIO2.0的异步特性也为编写高并发、非阻塞的代码提供了...
6. **文件系统API**:NIO.2提供了一个新的文件系统API,增强了对文件的操作,包括异步I/O和路径操作。 7. **改进的语法糖**:如动态类型和钻石操作符等,使得Java编程更简洁。 8. **并行化**:改进的并发工具,如...
NIO2(Non-Blocking I/O)是一种高性能的I/O操作方式,自Java 7开始引入,提供了许多新的API和方法来处理文件操作。下面是对NIO2基础的介绍,包括文件路径、Path类简介、符号链接等知识点。 文件路径是指文件在文件...
在文件系统操作上,JDK7引入了`java.nio.file`包,提供了一组新的API来处理文件和目录。`Path`类代表文件系统中的路径,`Files`类提供了各种文件操作的静态方法,如读写文件、创建目录、检查文件属性等。`...
`bin` 文件夹是 Java 开发工具包 (JDK) 中最重要的组成部分之一,它包含了多个关键性的可执行文件,这些文件对于 Java 程序的编译、运行以及开发过程中所需的其他功能至关重要。 1. **`javac.exe`**:这是一个 Java...
5. **文件系统API(NIO.2)**:引入了新的java.nio.file包,提供了更强大的文件操作功能,包括路径操作、文件属性查询以及异步I/O等。 6. **钻石运算符**:在创建匿名对象时,编译器可以自动推断出构造函数的参数...
4. **文件系统API增强**:Java 7引入了新的java.nio.file包,提供了更强大、更直观的文件操作API,如Path类和Files类,可以方便地进行文件和目录的操作。 5. **尝试(Try-with-resources)语句**:这个新特性使得...
安装完JDK后,会在%JAVA_HOME% /jdk文件夹下生成一个src.zip,此文件夹对应rt.jar中的java源码,但细心研究后发现rt.jar中sun包下的文件不存在,也就是说sun包下的java源码并没有打包到src.zip中。这个是jdk7u9版本...
4. **新的NIO.2 API**:增强了文件I/O操作的能力,支持文件观察者模式,简化了文件系统的访问。 5. **动态语言支持**:增加了对动态语言的支持,使得Java平台可以更好地支持如Groovy、Scala等动态语言。 6. **安全性...