`

JDK7 NIO2 监控文件夹文件拷贝完成

阅读更多

基于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);
        }
    }
}

 

 

 

 

 

 

1
0
分享到:
评论

相关推荐

    Pure JS (2): 热部署 (利用 JDK 7 NIO 监控文件变化)

    标题 "Pure JS (2): 热部署 (利用 JDK 7 NIO 监控文件变化)" 提到了一个关于JavaScript开发的话题,特别是热部署(Hot Deployment)的概念,这是一种在开发过程中无需重启应用就能自动更新代码的技术。...

    JDK_7_NIO2

    ### 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 ...

    使用jdk7的nio2操作文件拷贝和剪切示例

    在Java 7中引入的NIO.2(New IO 2.0)提供了一套全新的文件I/O API,显著地增强了对文件系统操作的支持。在这个示例中,我们将深入探讨如何使用NIO.2进行文件和目录的拷贝与移动操作。 首先,`copeOrMoveFile`方法...

    JDK1.7 无需安装,拷贝直接用

    7. **lib**:这个目录包含了JDK的各种库文件,如类库、JVM实现和开发工具所需的资源。 8. **bin**:包含可执行文件,如`java`, `javac`, `jar`等,是开发者最常使用的命令行工具。 9. **db**:可能是一个数据库,...

    新建文件夹jdk7 2 2.zip(从oracle官网下载)

    6. **文件系统API**:JDK 7引入了新的`java.nio.file`包,提供了符合POSIX标准的文件系统API,增强了文件操作的能力,如文件路径、文件属性和文件观察等。 7. **改进的垃圾收集**:JDK 7对垃圾收集器进行了优化,...

    基于jdk7文件监控定制

    jdk7 原生的监控包含很多编程细节, 实际工作不得不处理这些复杂的细节,这里进行轻量封装 提取出fileCreated,fileModified,fileDeleted,fileRenamed等更好用的接口

    JAVA NIO 按行读取大文件,支持 GB级别

    本类,是专门为了处理大文件,按行读取开发的类。 采用读文件的缓存 fbb 1024*5 行缓存 bb 256 字节 设计思想: 每次通过nio读取字节到 fbb中 然后对fbb自己中的内容进行行判断即 10 回车 13 行号 0 文件...

    JDK1.7文件夹形式

    JDK(Java Development Kit)是Oracle公司提供的用于开发和运行Java应用程序的软件工具包,而JDK 1.7,也被称为Java SE 7(Java Standard Edition 7),是Java语言的一个重要版本。它引入了许多新的特性和改进,以...

    JDK7免安装解压包

    7. **文件系统API(NIO.2)** 新的java.nio.file包提供了对文件系统的全面访问,包括文件、目录、符号链接和属性。API的设计更加面向对象,使得文件操作更加简洁和强大。 ### 配置环境变量 要使用这个免安装的JDK...

    FileMonitor 基于jdk7文件监控WatchService

    《基于JDK7的FileMonitor:精简版文件监控服务详解》 在Java开发中,对文件系统的实时监控是一项常用且重要的任务。JDK7引入了`WatchService`接口,为开发者提供了一种监听文件系统变化的能力。然而,`WatchService...

    jdk7 jdk-7u80-linux-x64 网盘下载

    为了更好地支持现代文件系统的需求,JDK 7引入了新的NIO.2 API(New I/O),该API提供了一种更为灵活的方式来处理文件路径、文件锁定以及异步文件I/O操作。 ##### 2.3 多线程编程增强 JDK 7增加了对Fork/Join框架...

    利用JDK7的NIO2.0进行I/O读写和监视

    学习和理解JDK7的NIO2.0对于提升Java应用的性能和可扩展性至关重要,尤其是在处理大量I/O操作的场景下,如文件服务器、日志系统或者大型数据处理应用。同时,NIO2.0的异步特性也为编写高并发、非阻塞的代码提供了...

    jdk 7版本安装包

    6. **文件系统API**:NIO.2提供了一个新的文件系统API,增强了对文件的操作,包括异步I/O和路径操作。 7. **改进的语法糖**:如动态类型和钻石操作符等,使得Java编程更简洁。 8. **并行化**:改进的并发工具,如...

    NIO2基础介绍

    NIO2(Non-Blocking I/O)是一种高性能的I/O操作方式,自Java 7开始引入,提供了许多新的API和方法来处理文件操作。下面是对NIO2基础的介绍,包括文件路径、Path类简介、符号链接等知识点。 文件路径是指文件在文件...

    jdk7api帮助文档

    在文件系统操作上,JDK7引入了`java.nio.file`包,提供了一组新的API来处理文件和目录。`Path`类代表文件系统中的路径,`Files`类提供了各种文件操作的静态方法,如读写文件、创建目录、检查文件属性等。`...

    JDK路径下各个文件夹的作用.pdf

    `bin` 文件夹是 Java 开发工具包 (JDK) 中最重要的组成部分之一,它包含了多个关键性的可执行文件,这些文件对于 Java 程序的编译、运行以及开发过程中所需的其他功能至关重要。 1. **`javac.exe`**:这是一个 Java...

    jdk-7u80-windows-x64.exe 【官方下载的jdk1.7、jdk7,windows 64位版】

    5. **文件系统API(NIO.2)**:引入了新的java.nio.file包,提供了更强大的文件操作功能,包括路径操作、文件属性查询以及异步I/O等。 6. **钻石运算符**:在创建匿名对象时,编译器可以自动推断出构造函数的参数...

    JDK7 Windows32位

    4. **文件系统API增强**:Java 7引入了新的java.nio.file包,提供了更强大、更直观的文件操作API,如Path类和Files类,可以方便地进行文件和目录的操作。 5. **尝试(Try-with-resources)语句**:这个新特性使得...

    jdk7 jdk-7u80-windows-x64 网盘下载

    4. **新的NIO.2 API**:增强了文件I/O操作的能力,支持文件观察者模式,简化了文件系统的访问。 5. **动态语言支持**:增加了对动态语言的支持,使得Java平台可以更好地支持如Groovy、Scala等动态语言。 6. **安全性...

    JDK7新特性(完整篇)

    4. **JDK7新特性&lt;四&gt; NIO2.0 文件系统** NIO2(非阻塞I/O的第二版)带来了全新的文件系统接口,包括Path API、WatchService API等,提供了异步文件操作和文件事件监听的能力,极大地提升了文件操作的灵活性和性能。...

Global site tag (gtag.js) - Google Analytics