Rumah  >  Artikel  >  Java  >  java利用WatchService实时监控某个目录下的文件变化并按行解析实例详解

java利用WatchService实时监控某个目录下的文件变化并按行解析实例详解

怪我咯
怪我咯asal
2017-06-25 10:11:281706semak imbas

首先说下需求:通过ftp上传约定格式的文件到服务器指定目录下,应用程序能实时监控该目录下文件变化,如果上传的文件格式符合要求,将将按照每一行读取解析再写入到数据库,解析完之后再将文件改名。

一. 一开始的思路

  设置一个定时任务,每隔一分钟读取下指定目录下的文件变化,如果有满足格式的文件,就进行解析。

     这种方式很繁琐,而且效率低,效率都消耗在了遍历、保存状态、对比状态上了! 而且无法利用OS的很多功能。

 

二. WatchService介绍

1、 该类的对象就是操作系统原生的文件系统监控器!我们都知道OS自己的文件系统监控器可以监控系统上所有文件的变化,这种监控是无需遍历、无需比较的,是一种基于信号收发的监控,因此效率一定是最高的;现在Java对其进行了包装,可以直接在Java程序    中使用OS的文件系统监控器了;

2、 获取当前OS平台下的文件系统监控器:

         i. WatchService watcher = FileSystems.getDefault().newWatchService();

         ii. 从FileSystems这个类名就可以看出这肯定是属于OS平台文件系统的,接下来可以看出这一连串方法直接可以得到一个文件监控器;

  这里暂时不用深入理解这串方法的具体含义,先知道怎么用就行了;

3、 我们都知道,操作系统上可以同时开启多个监控器,因此在Java程序中也不例外,上面的代码只是获得了一个监控器,你还可以用同样的代码同时获得多个监控器;

4、 监控器其实就是一个后台线程,在后台监控文件变化所发出的信号,这里通过上述代码获得的监控器还只是一个刚刚初始化的线程,连就绪状态都没有进入,只是初始化而已;

 

三、实现过程

  其实就是在初始化的时候创建一个线程,然后用watchService实时监控该目录下文件变化,如果有满足条件文件加进来,就按照约定的格式解析文件再写入数据库,详细步骤如下!

  1、web.xml监听器配置文件监控监听器  

930406f08da8ee4a2ff134b688d29d1dcd65b3a4eec0dfd2b520f594bda16a0f75d9475f58d50d678ef97bf7ae35ef75c13d9669d2c8f87a36a39c8f95f41552contextConfigLocation02b9ad8b27bc78bd91c18db845cdde4af226acac8cb0e4a9d59fcba58b57a899classpath:root-context.xml22c8aeb51b7638a9da01bd5a66154ac11c0ed9b29d4061c50424e545cf7b2ba51d24e586ca31f4bd05eca427459d98c7f573a9ccb524cb86b6b9919be70810beCharacterEncodingFilterb4d5e6fde2c78ede331e20c60d37da11e5b954f5d6752e2b67f5dbec1cf5c85eorg.springframework.web.filter.CharacterEncodingFilter3c5315e9114c0f42d7a83b06562caa88380fae52cc7d04565d26dd4bbf4b5460c13d9669d2c8f87a36a39c8f95f41552encoding02b9ad8b27bc78bd91c18db845cdde4af226acac8cb0e4a9d59fcba58b57a899UTF-822c8aeb51b7638a9da01bd5a66154ac18f161518881ffd7712eaaadc573a3556380fae52cc7d04565d26dd4bbf4b5460c13d9669d2c8f87a36a39c8f95f41552forceEncoding02b9ad8b27bc78bd91c18db845cdde4af226acac8cb0e4a9d59fcba58b57a899true22c8aeb51b7638a9da01bd5a66154ac18f161518881ffd7712eaaadc573a355694e66dfbd9fa8f117002935bdd35d0b3dd0dfb26ea66647667f179a739921d33f573a9ccb524cb86b6b9919be70810beCharacterEncodingFilterb4d5e6fde2c78ede331e20c60d37da1166e1775cbd9d5002635ae3285442ba88/*3ec4a5583206d351b61ed79c1a0f9c66e354d6d34e50ca0d695db95544b3672a1d24e586ca31f4bd05eca427459d98c7f573a9ccb524cb86b6b9919be70810besitemeshb4d5e6fde2c78ede331e20c60d37da11e5b954f5d6752e2b67f5dbec1cf5c85ecom.opensymphony.sitemesh.webapp.SiteMeshFilter3c5315e9114c0f42d7a83b06562caa8894e66dfbd9fa8f117002935bdd35d0b3dd0dfb26ea66647667f179a739921d33f573a9ccb524cb86b6b9919be70810besitemeshb4d5e6fde2c78ede331e20c60d37da1166e1775cbd9d5002635ae3285442ba88/*3ec4a5583206d351b61ed79c1a0f9c66e354d6d34e50ca0d695db95544b3672a46309ed845064fdb06e746051efff9e0700b5f17c4d842e4bd410f680f40946bappServlet72eca723e64ddd01187c8b4d58572fcbb472d9135dbff3dd7fcc77f5995c97d0org.springframework.web.servlet.DispatcherServlet4f01b97d64aea37f699ead4eb7bd2bbd380fae52cc7d04565d26dd4bbf4b5460c13d9669d2c8f87a36a39c8f95f41552contextConfigLocation02b9ad8b27bc78bd91c18db845cdde4af226acac8cb0e4a9d59fcba58b57a899classpath:servlet-context.xml22c8aeb51b7638a9da01bd5a66154ac18f161518881ffd7712eaaadc573a35564781e2cbaa93c386271b418d3a01af0813065abc64b27fbca30c0905ab93e8ea020d42bb762ac7d7e594da3a264e47fcc870ae7edaa11700bcea972d006efb06e700b5f17c4d842e4bd410f680f40946bappServlet72eca723e64ddd01187c8b4d58572fcb66e1775cbd9d5002635ae3285442ba88/3ec4a5583206d351b61ed79c1a0f9c66cb808b0e21d3ee32c89fe10adc3f12ecf3f5604d5528b766199471609c7e722eeae7f28921fa176b20e23abb843be0905948543310f2c9ae6eabc90d07fdac18org.springframework.web.context.ContextLoaderListenera5cb73ed00d90e1dafbf6168c4a676c2f26bc28f07f75d604e1d9c5e7de10123de02ef028bd8b9a79de42b2beabf35ebeae7f28921fa176b20e23abb843be0905948543310f2c9ae6eabc90d07fdac18com.zealer.ad.listener.ThreadStartUpListensera5cb73ed00d90e1dafbf6168c4a676c2f26bc28f07f75d604e1d9c5e7de10123eae7f28921fa176b20e23abb843be0905948543310f2c9ae6eabc90d07fdac18com.zealer.ad.listener.SessionLifecycleListenera5cb73ed00d90e1dafbf6168c4a676c2f26bc28f07f75d604e1d9c5e7de10123
    f0e92f654589c392f4bce55576ef09df  f1e8976e483ae51232e262b5342c464c   fa71b69717bc99e9a78fbc85d8a96339/tag09895297a0aa8662f06901bffdbb71d1   96344b67689bfb9376de746be45b7a6b/WEB-INF/tag/tag.tldbafd8e2dbced6979955b7cae9142033d  328c2203205d81cf46ea0b2c6a2671eeec05f097bfa9cd9364ff55ce9622d108145f58f625840b9ea02ee646738753d64dc738b987c616c936501769be741a6eindex.jsp61b13b5331cf95fd092fcea0d23c370c300e6fadd23fafd1b065a779b865fda92154b31975826eec7c9ecbf8f296fb33ac238ff21ee5e16243d046a43ee626d2453152a4ea4663b36e0b3abf7880663fbce74d0d5e0feeabcbab17c56a2dfd7fed9ec23d40699efb4cb39a61797a06a5a1

  2、编写一个ThreadStartUpListenser类,实现ServletContextListener,tomcat启动时创建后台线程

  ThreadStartUpListenser.java

package com.zealer.ad.listener;import javax.servlet.ServletContextEvent;import javax.servlet.ServletContextListener;import org.apache.commons.logging.Log;import org.apache.commons.logging.LogFactory;import org.springframework.stereotype.Component;import com.zealer.ad.task.WatchFilePathTask;

@Componentpublic class ThreadStartUpListenser implements ServletContextListener
{private static WatchFilePathTask r = new WatchFilePathTask();private Log log = LogFactory.getLog(ThreadStartUpListenser.class);    /* * tomcat启动的时候创建一个线程
     * */@Overridepublic void contextInitialized(ServletContextEvent paramServletContextEvent)
    {
        r.start();
        log.info("ImportUserFromFileTask is started!");
    }    /* * tomcat关闭的时候销毁这个线程
     * */@Overridepublic void contextDestroyed(ServletContextEvent paramServletContextEvent)
    {
        r.interrupt();
    }

}

  3、创建指定目录文件变化监控类

    WatchFilePathTask.java

  WatchFilePathTask  Log log = LogFactory.getLog(WatchFilePathTask.   String filePath = ConfigUtils.getInstance().getValue("userfile_path" watchService ="获取监控服务"+="@@@:Path:"+ String todayFormat = DateTime.now().toString("yyyyMMdd"= = existFiles.listFiles( ((todayFormat+".txt"  ( !=ImportUserFromFileTask task = (ImportUserFromFileTask) SpringUtils.getApplicationContext().getBean("importUserFromFileTask"WatchKey key = (= (WatchEvent6b3d0130bba23ae47fe2b8e8cddf0195String fileName =((todayFormat+".txt"= path.toFile().getAbsolutePath()+File.separator+"import filePath:"+ImportUserFromFileTask task = (ImportUserFromFileTask) SpringUtils.getApplicationContext().getBean("importUserFromFileTask");"启动线程导入用户数据"+

  4、创建解析用户文件及导入数据库线程,由WatchFilePathTask启动

package com.zealer.ad.task;import com.zealer.ad.entity.AutoPutUser;import com.zealer.ad.entity.Bmsuser;import com.zealer.ad.service.AutoPutUserService;import org.apache.commons.logging.Log;import org.apache.commons.logging.LogFactory;import org.joda.time.DateTime;import java.io.BufferedReader;import java.io.File;import java.io.FileInputStream;import java.io.InputStreamReader;import java.util.Date;import javax.annotation.Resource;/**
 * 解析用户文件及入库线程,由WatchFilePathTask启动
 * @author cancer
 * */public class ImportUserFromFileTask extends Thread {private Log log = LogFactory.getLog(ImportUserFromFileTask.class);private String fileName;
    @Resource(name = "autoPutUserService")private AutoPutUserService autoPutUserService;

    @Overridepublic void run() {
        File file = new File(fileName);if (file.exists() && file.isFile()) {
            log.debug(":@@@准备开始休眠10秒钟:" + file);//休眠十分钟,防止文件过大还没完全拷贝到指定目录下,这里的线程就开始读取文件try {
                sleep(10000);
            } catch (InterruptedException e1) {
                e1.printStackTrace();
            }

            InputStreamReader read;try {
                read = new InputStreamReader(new FileInputStream(file), "UTF-8");

                BufferedReader bufferedReader = new BufferedReader(read);
                String lineTxt = null;int count = 0;
                Boolean f = false;while ((lineTxt = bufferedReader.readLine()) != null) {if ((null == lineTxt) || "".equals(lineTxt)) {continue;
                    }if (lineTxt.startsWith("'")) {
                        lineTxt = lineTxt.substring(1, lineTxt.length());
                    }//解析分隔符为', 'String[] lines = lineTxt.split("', '");int length = lines.length;if (length < 2) {continue;
                    }

                    Bmsuser bmsuser = new Bmsuser();
                    bmsuser.setName(lines[0]);if (!"".equals(lines[1])) {
                        bmsuser.setCity(lines[1]);
                    }
            //根据唯一索引已经存在的数据则不插入f = autoPutUserService.insertIgnore(bmsuser);if (f) {
                        count++;
                    }
                }//汇总数据AutoPutUser autoPutUser = new AutoPutUser();
                autoPutUser.setTotalCount(autoPutUserService.getUserCount());
                autoPutUser.setCount(count);
                autoPutUser.setCountDate(new Date(System.currentTimeMillis()));

                String today = DateTime.now().toString("yyyy-MM-dd");
                Integer oldCount = autoPutUserService.getOldCount(today);//如果今天导入过了就更新否则插入if (!oldCount.equals(0)) {
                    autoPutUserService.updateUserData(autoPutUser, today,
                        oldCount);
                } else {
                    autoPutUserService.gatherUserData(autoPutUser);
                }//注意:要关闭流                read.close();
            } catch (Exception e) {
                log.error(e.getMessage(), e);
            }

            File newFile = new File(file.getPath() +System.currentTimeMillis() + ".complate");
            file.renameTo(newFile);
        } else {
            log.error(fileName + " file is not exists");
        }
    }public String getFileName() {return fileName;
    }public void setFileName(String fileName) {this.fileName = fileName;
    }public AutoPutUserService getAutoPutUserService() {return autoPutUserService;
    }public void setAutoPutUserService(AutoPutUserService autoPutUserService) {this.autoPutUserService = autoPutUserService;
    }
}

 

附带:

1、sql脚本

CREATE TABLE `bmsuser` (
  `id` int(255) unsigned NOT NULL AUTO_INCREMENT,
  `name` varchar(32) DEFAULT NULL ,
  `city` varchar(32) DEFAULT NULL COMMENT ,  PRIMARY KEY (`bmsid`),  UNIQUE KEY `bbLoginName` (`bbLoginName`)
) ENGINE=InnoDB  DEFAULT CHARSET=utf8;

2、文件格式,命名为yyyyMMdd.txt

&#39;张三&#39;, &#39;深圳&#39;

 

Atas ialah kandungan terperinci java利用WatchService实时监控某个目录下的文件变化并按行解析实例详解. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Kenyataan:
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn