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

怪我咯

怪我咯

2017-06-25

2079人浏览

原创

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

一. 一开始的思路

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

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

 

二. WatchService介绍

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

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

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

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

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

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

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

Java JDK 25
Java JDK 25

Java JDK 25 来自 OpenJDK 官方归档,版本为 JDK 25,本条下载地址已指向官方 Windows x64 zip 安装包直链,适合调试旧项目或兼容旧版 Java 运行环境。

下载

 

三、实现过程

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

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

<?xml  version="1.0" encoding="UTF-8"?><web-app><context-param><param-name>contextConfigLocation</param-name><param-value>classpath:root-context.xml</param-value></context-param><filter><filter-name>CharacterEncodingFilter</filter-name><filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class><init-param><param-name>encoding</param-name><param-value>UTF-8</param-value></init-param><init-param><param-name>forceEncoding</param-name><param-value>true</param-value></init-param></filter><filter-mapping><filter-name>CharacterEncodingFilter</filter-name><url-pattern>/*</url-pattern></filter-mapping><filter><filter-name>sitemesh</filter-name><filter-class>com.opensymphony.sitemesh.webapp.SiteMeshFilter</filter-class></filter><filter-mapping><filter-name>sitemesh</filter-name><url-pattern>/*</url-pattern></filter-mapping><servlet><servlet-name>appServlet</servlet-name><servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class><init-param><param-name>contextConfigLocation</param-name><param-value>classpath:servlet-context.xml</param-value></init-param><load-on-startup>1</load-on-startup></servlet><servlet-mapping><servlet-name>appServlet</servlet-name><url-pattern>/</url-pattern></servlet-mapping><!-- 配置spring监听器 --><listener><listener-class>org.springframework.web.context.ContextLoaderListener</listener-class></listener><!-- 配置监控文件变化监听器 --><listener><listener-class>com.zealer.ad.listener.ThreadStartUpListenser</listener-class></listener><listener><listener-class>com.zealer.ad.listener.SessionLifecycleListener</listener-class></listener>
    <jsp-config>  <taglib>   <taglib-uri>/tag</taglib-uri>   <taglib-location>/WEB-INF/tag/tag.tld</taglib-location>  </taglib></jsp-config><welcome-file-list><welcome-file>index.jsp</welcome-file></welcome-file-list><session-config><session-timeout>45</session-timeout></session-config></web-app>

  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 = (= (WatchEvent>String 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 

 

附带:

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

'张三', '深圳'

 

Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南

相关专题

更多
墨刀AI提示词教学
墨刀AI提示词教学

本合集由PHP中文网精心整理,为您提供全面的墨刀AI提示词教学。内容涵盖高质量原型撰写公式与实操窍门,助您轻松掌握AI设计工具。无论是零基础入门还是进阶技巧,都能让您快速上手,大幅提升产品设计与协作效率。

2026.08.04

10

21

墨刀AI完整入门
墨刀AI完整入门

PHP中文网为您倾力打造墨刀AI保姆级入门指南完整版!本合集从零基础讲起,涵盖AI生成原型、提示词优化、图片转原型及多轮对话等核心功能。无论您是新手还是进阶用户,都能轻松掌握产品设计全流程。快来PHP中文网,一键解锁高效设计技巧,让想法即刻成型!

2026.08.04

8

20

墨刀AI进阶技巧
墨刀AI进阶技巧

本合集由PHP中文网精心整理,为您提供墨刀AI核心进阶策略指南。内容涵盖高效提示词写作、原型智能生成与微调、结构化导图制作及行业分析报告输出等实战技巧。助您轻松掌握AI设计工具,大幅提升产品设计与团队协作效率。

2026.08.04

10

14

火山引擎实名认证失败怎么办
火山引擎实名认证失败怎么办

火山引擎实名认证失败可能与证件信息填写错误、姓名或企业信息不一致、证件照片不清晰、营业执照状态异常、手机号验证失败或审核资料不完整有关。本专题整理个人认证、企业认证、资料上传、审核退回、重新提交和认证不通过的常见处理方法。

2026.08.04

5

10

火山引擎域名备案流程详解
火山引擎域名备案流程详解

火山引擎域名备案适合需要在火山引擎云服务器、对象存储、CDN或网站服务上绑定域名的用户参考。本专题整理备案入口、账号实名认证、备案类型选择、主体信息填写、网站信息提交、资料上传、初审核验、管局审核和备案失败排查,帮助用户完成网站上线前的备案流程。

2026.08.04

1

10

火山引擎DNS解析配置步骤
火山引擎DNS解析配置步骤

使用火山引擎DNS解析网站域名时,需要确认域名已完成管理接入,并正确配置服务器IP、CNAME地址或验证记录。本专题整理域名添加、记录类型选择、TTL设置、解析状态检查、备案和访问测试等流程,适合新手搭建网站时参考。

2026.08.04

3

10

火山引擎对象存储使用教程
火山引擎对象存储使用教程

火山引擎对象存储适合用于网站图片、视频文件、备份数据、静态资源和应用附件管理。本专题整理TOS控制台入口、存储桶创建、地域选择、权限设置、文件上传、访问链接生成、CDN加速、费用查看和常见上传或访问失败问题,帮助用户快速掌握对象存储基础操作。

2026.08.04

1

10

火山引擎云服务器使用教程
火山引擎云服务器使用教程

火山引擎云服务器使用教程适合第一次购买、部署和管理云服务器的用户参考。本专题整理控制台入口、实例创建、地域和配置选择、系统镜像设置、安全组放行、远程连接、网站部署、续费计费和常见连接失败问题,帮助用户快速完成云服务器基础使用流程。

2026.08.04

5

10

火山引擎API Key绑定大模型教程
火山引擎API Key绑定大模型教程

火山引擎API Key怎么绑定大模型适合需要在火山方舟、应用后台、脚本工具或AI编程软件中调用模型的开发者参考。本专题整理控制台服务开通、API Key创建、模型权限检查、模型ID选择、Base URL填写、调用测试和鉴权失败排查,帮助用户完成从密钥到模型调用的配置流程。

2026.08.04

2

10

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
Java JDBC数据库连接官方教程
Java JDBC数据库连接官方教程

共0课时 | 0人学习

Java 26官方文档
Java 26官方文档

共0课时 | 0人学习