java实时监控文件,如果文件被修改,每次按行获取文件更新内容

一、概述:

使用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 效果展示

  • 查看目标文件和数据库,初始为空
  • 向文件写入一行数据,并保存
  • 查看数据库,发现落库成功
  • 多添加几条数据,发现依据落库成功

猜你喜欢

转载自blog.csdn.net/qq_56044050/article/details/124214228