一、概述:
使用java实现对文件的监控功能,当文件发生修改,实时获取更新内容。
1.要求对目标文件实时监控
2.按行读取文件更行内容
3.将获取内容进行落库
二、使用技术:
2.1 commons-io
使用Commons-io的monitor下的相关类可以处理对文件进行监控,它采用的是观察者模式来实现的
- (1)可以监控文件夹的创建、删除和修改
- (2)可以监控文件的创建、删除和修改
- (3)采用的是观察者模式来实现的
- (4)采用线程去定时去刷新检测文件的变化情况
2.2 RandomAccessFile
RandomAccessFile的唯一父类是Object,与其他流父类不同。RandomAccessFile通常用来访问那些保存数据记录的文件的,它提供了seek( )方法来访问记录,可以从记录位置进行读写操作,这些记录的大小不必相同;但是其大小和位置必须是可知的。
三、具体步骤
3.1 引入commons-io包,需要2.0以上
<!-- https://mvnrepository.com/artifact/commons-io/commons-io -->
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.6</version>
</dependency>
3.2 编写继承FileAlterationListenerAdaptor的类FileListener
package utils;
import java.io.File;
import java.io.IOException;
import org.apache.commons.io.monitor.FileAlterationListenerAdaptor;
import org.apache.commons.io.monitor.FileAlterationObserver;
public class FileListener extends FileAlterationListenerAdaptor {
ReadTest readTest = new ReadTest();
/**
* 文件创建执行
*/
public void onFileCreate(File file) {
//也可以打印日志
System.out.println("文件[新建]:" + file.getAbsolutePath());
}
/**
* 文件创建修改
*/
public void onFileChange(File file) {
System.out.println("文件[修改]:" + file.getAbsolutePath());
//目标文件路径
String str = "d:\\test\\est.txt";
//如果被修改的是目标文件,执行自己的业务操作
if(str.equals(file.getAbsolutePath())){
try {
readTest.readAW();
} catch (IOException e) {
e.printStackTrace();
}
}
}
/**
* 文件删除
*/
public void onFileDelete(File file) {
System.out.println("文件[删除]:" + file.getAbsolutePath());
}
/**
* 目录创建
*/
public void onDirectoryCreate(File directory) {
System.out.println("[新建]:" + directory.getAbsolutePath());
}
/**
* 目录修改
*/
public void onDirectoryChange(File directory) {
System.out.println("[修改]:" + directory.getAbsolutePath());
}
/**
* 目录删除
*/
public void onDirectoryDelete(File directory) {
System.out.println("[删除]:" + 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);
}
}
- 文件监控的原理如下:
- 由文件监控类FileAlterationMonitor中的线程不停的扫描文件观察FileAlterationObserver, 如果有文件的变化,则根据相关的文件比较器,判断文件时新增,还是删除,还是更改。(默认为1000毫秒执行一次扫描)
3.3 实现main方法
public static void main(String[] args) throws Exception{
// 监控目录
String rootDir = "D://test";
// 轮询间隔
long interval = TimeUnit.SECONDS.toMillis(1);
// 创建过滤器
IOFileFilter directories = FileFilterUtils.and(
// 只监听文件夹、目录
FileFilterUtils.directoryFileFilter(),
// 此过滤器接受File隐藏的
HiddenFileFilter.VISIBLE);
IOFileFilter files = FileFilterUtils.and(
// 只监听文件
FileFilterUtils.fileFileFilter(),
// 只监听文件后缀为txt的文件
FileFilterUtils.suffixFileFilter(".txt"));
IOFileFilter filter = FileFilterUtils.or(directories, files);
// 使用过滤器
FileAlterationObserver observer = new FileAlterationObserver(new File(rootDir), filter);
//不使用过滤器
//FileAlterationObserver observer = new FileAlterationObserver(new File(rootDir));
observer.addListener(new FileListener());
//创建文件变化监听器
FileAlterationMonitor monitor = new FileAlterationMonitor(interval, observer);
// 开始监控
monitor.start();
}
到此为止,文件监听完成。现在启动main()方法,然后对目标文件进行操作,监听器监听到目标文件发生修改,便会执行FileListener类下onFileChange()中的指定操作。
接下来实现按行读取文本更新内容,需要用到RandomAccessFile
3.4 实现readAW()(自己的业务操作)
public class ReadTest {
//设置变量 记录上次读取位置
private long num = 0;
public void readAW() throws IOException {
File file = new File("d://test//est.txt");
RandomAccessFile randomAccessFile = new RandomAccessFile(file,"rw");
//将文件定位到偏移量所指位置,在该位置发生下一个读取或写入操作
randomAccessFile.seek(num);
//获取按行读取的数据并落库
String s = randomAccessFile.readLine();
for(;s!= null;s = randomAccessFile.readLine()){
User user = new User();
user.setUserName(s);
userServer.insertUser(user);
}
//重新计算偏移量,做下一次读取时的初始偏移量
num= randomAccessFile.length();
}
}
注意:这种写法只能获取到每次更新向文件尾部追加内容,对于文件之前内容的修改不可知
3.5 效果展示
- 查看目标文件和数据库,初始为空
- 向文件写入一行数据,并保存
- 查看数据库,发现落库成功
- 多添加几条数据,发现依据落库成功