1 问题描述
使用Commons-io的monitor下的相关类可以监控文件夹和文件的创建、删除和修改,它采用的是观察者模式来实现的。
但是当文件数据量较大的时候,例如往监控的文件夹传输zip之后进行解压的时候,由于文件过大,会多次触发onFileChange(),而且并不知道什么时候结束,也不知道什么时候是最后一次onFileChange(),未完成解压时就会报错。
2 解决方式
这里采用了定时器Timer
设置一个计数器COUNT
设置一个最终延迟DELAY
在每次触发onFileChange()的时候启动一个TimeTask
开始计时,每次将COUNT置为0,
启动TimeTask递增COUNT,当下一次onFileChange()触发时,
COUNT又一次置为0, 此时临时的tempCount != COUNT,
表示还在传输,当COUNT = DELAY 的时候,此时判定文件已经传完了
(这个DELAY应该大于两次onFileChange()的间隔,受传输速率影响)
3 代码
import org.apache.commons.io.monitor.FileAlterationListenerAdaptor;
import org.apache.commons.io.monitor.FileAlterationObserver;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.File;
import java.util.HashMap;
import java.util.Map;
import java.util.Timer;
import java.util.TimerTask;
/**
* 文件变化监听器
*
* 在Apache的Commons-IO中有关于文件的监控功能的代码. 文件监控的原理如下:
* 由文件监控类FileAlterationMonitor中的线程不停的扫描文件观察器FileAlterationObserver,
* 如果有文件的变化,则根据相关的文件比较器,判断文件时新增,还是删除,还是更改。(默认为1000毫秒执行一次扫描)
*
*
*/
public class FileListener extends FileAlterationListenerAdaptor {
public static final Logger logger = LoggerFactory.getLogger(FileListener.class);
private static final int DELAY = 10;
private static int COUNT = 0;
private static Timer timer = new Timer();
public void setTimer(String compressedPath) {
COUNT= 0;
timer.schedule(new TimerTask() {
public void run() {
try {
setCount(compressedPath);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}, 0); // 此处delay为0表示没有延迟,立即执行一次task
}
public void setCount(String compressedPath) throws InterruptedException {
int tempCount = 0;
COUNT = 0;
for(int i=0;i<DELAY;i++){
Thread.sleep(1000);
tempCount++;
COUNT++;
logger.info("tempCount:"+tempCount+" COUNT:"+COUNT);
if(tempCount!=COUNT){
logger.info("return");
return;
}
}
try {
//调用文件扫描任务当中的压缩包解析版,传递压缩包路径
//decompress(compressedPath);
} catch (Exception e) {
e.printStackTrace();
logger.error("任务出错!");
}
}
/**
* 文件创建执行
*/
public void onFileCreate(File file) {
String compressedPath = file.getAbsolutePath();
logger.info("[新建]:" + compressedPath);
setTimer(compressedPath);
}
/**
* 文件创建修改,新建文件之后都会触发修改
*/
public void onFileChange(File file) {
String compressedPath = file.getAbsolutePath();
logger.info("[修改]:" + compressedPath);
setTimer(compressedPath);
}
/**
* 文件删除
*/
public void onFileDelete(File file) {
logger.info("[删除]:" + file.getAbsolutePath());
}
/**
* 目录创建
*/
public void onDirectoryCreate(File directory) {
logger.info("[新建]:" + directory.getAbsolutePath());
}
/**
* 目录修改
*/
public void onDirectoryChange(File directory) {
logger.info("[修改]:" + directory.getAbsolutePath());
}
/**
* 目录删除
*/
public void onDirectoryDelete(File directory) {
logger.info("[删除]:" + directory.getAbsolutePath());
}
public void onStart(FileAlterationObserver observer) {
// TODO Auto-generated method stub
super.onStart(observer);
}
public void onStop(FileAlterationObserver observer) {
// TODO Auto-generated method stub
super.onStop(observer);
}
}