Java实现文件监控器FileMonitor的实例代码

应用场景:

代码可以实现文件变化后的监听,如文件变化,自动重新加载文件内容,实现配置文件的热部署。

代码:

package com.yx.demo.filemonitor;

import java.io.File;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Timer;
import java.util.TimerTask;

/**
 * FileMonitor
 * 文件监控器
 *
 * @author yx
 * @date 2019/12/21 0:59
 */
public class FileMonitor {

  /**
   * 每2秒更新的默认监控器
   */
  private static FileMonitor defaultFileMonitor = new FileMonitor(2 * 1000);

  private Timer timer_;
  private HashMap<File, FileEntry> files_; // File -> Long
  private List<FileEntry> fileEntrys = new java.util.concurrent.CopyOnWriteArrayList<FileEntry>();
  private Collection<WeakReference<FileListener>> listeners_; // of WeakReference(FileListener)

  private long pollingInterval = 10000;

  public static FileMonitor getDefaultFileMonitor() {
    return defaultFileMonitor;
  }

  /**
   * Create a file monitor instance with specified polling interval.
   *
   * @param pollingInterval Polling interval in milli seconds.
   */
  public FileMonitor(long pollingInterval) {
    this.pollingInterval = pollingInterval;

    files_ = new HashMap<File, FileEntry>();
    listeners_ = new ArrayList<WeakReference<FileListener>>();

    timer_ = new Timer("FileMonitor", true);
    timer_.schedule(new FileMonitorNotifier(), 0, pollingInterval);
  }

  /**
   * Stop the file monitor polling.
   */
  public void stop() {
    timer_.cancel();
    timer_ = null;
  }

  public void start() {
    if (timer_ == null) {
      timer_ = new Timer(true);
      timer_.schedule(new FileMonitorNotifier(), 0, pollingInterval);
    }
  }

  /**
   * Add file to listen for. File may be any java.io.File (including a
   * directory) and may well be a non-existing file in the case where the
   * creating of the file is to be trepped.
   * <p>
   * More than one file can be listened for. When the specified file is
   * created, modified or deleted, listeners are notified.
   *
   * @param file File to listen for.
   */
  public void addFile(String id, File file) {
    if (!files_.containsKey(file)) {

      FileEntry entry = new FileEntry(id, file, file.exists() ? file.lastModified() : -1);
      files_.put(file, entry);
    }
  }

  /**
   * 添加监控文件实体。
   *
   * @param fileEntry
   */
  public void addFileEntry(FileEntry fileEntry) {
    if (!fileEntrys.contains(fileEntry)) {
      fileEntrys.add(fileEntry);
    }
  }

  /**
   * 通过文件实体的标识判断监控文件实体是否存在。
   *
   * @param id
   * @return
   */
  public boolean fileEntryExists(String id) {
    if (id == null) {
      return false;
    }

    for (int i = 0; i < fileEntrys.size(); i++) {
      if (id.equals(fileEntrys.get(i).getId())) {
        return true;
      }
    }

    return false;
  }

  /**
   * 通过文件实体标识删除一个监控文件实体。
   *
   * @param id
   */
  public void removeFileEntry(String id) {
    if (id == null) {
      return;
    }

    for (int i = 0; i < fileEntrys.size(); i++) {
      if (id.equals(fileEntrys.get(i).getId())) {
        fileEntrys.remove(i);
        return;
      }
    }
  }

  /**
   * Remove specified file for listening.
   *
   * @param file File to remove.
   */
  public void removeFile(File file) {
    files_.remove(file);
  }

  /**
   * Add listener to this file monitor.
   *
   * @param fileListener Listener to add.
   */
  public void addListener(FileListener fileListener) {
    // Don't add if its already there
    for (Iterator<WeakReference<FileListener>> i = listeners_.iterator(); i.hasNext(); ) {
      WeakReference<FileListener> reference = i.next();
      FileListener listener = (FileListener) reference.get();
      if (listener == fileListener) {
        return;
      }
    }

    // Use WeakReference to avoid memory leak if this becomes the
    // sole reference to the object.
    listeners_.add(new WeakReference<FileListener>(fileListener));
  }

  /**
   * Remove listener from this file monitor.
   *
   * @param fileListener Listener to remove.
   */
  public void removeListener(FileListener fileListener) {
    for (Iterator<WeakReference<FileListener>> i = listeners_.iterator(); i.hasNext(); ) {
      WeakReference<FileListener> reference = (WeakReference<FileListener>) i.next();
      FileListener listener = (FileListener) reference.get();
      if (listener == fileListener) {
        i.remove();
        break;
      }
    }
  }

  /**
   * This is the timer thread which is executed every n milliseconds according
   * to the setting of the file monitor. It investigates the file in question
   * and notify listeners if changed.
   */
  private class FileMonitorNotifier extends TimerTask {
    @Override
    public void run() {
      try {
        for (Iterator<FileEntry> i = fileEntrys.iterator(); i.hasNext(); ) {
          try {
            FileEntry entry = i.next();
            if (entry == null || !entry.check()) {
              i.remove();
            }
          } catch (Throwable t) {
            t.printStackTrace();
            System.out.println("执行文件监控发生错误:" + t.getMessage());
          }
        }

        // Loop over the registered files and see which have changed.
        // Use a copy of the list in case listener wants to alter the
        // list within its fileChanged method.
        Collection<File> files = new ArrayList<File>(files_.keySet());

        for (Iterator<File> i = files.iterator(); i.hasNext(); ) {
          File file = i.next();
          try {
            FileEntry fileEntry = files_.get(file);
            long lastModifiedTime = fileEntry.getLastModified();
            long newModifiedTime = file.exists() ? file.lastModified() : -1;

            //logger.debug(file.getAbsolutePath());
            //logger.debug("  {}=>{}", lastModifiedTime, newModifiedTime);
            // Chek if file has changed
            if (newModifiedTime != lastModifiedTime) {
              //logger.debug("file changed {})", file.getAbsolutePath());
              fileEntry.setLastModified(newModifiedTime);
              // Register new modified time
              files_.put(file, fileEntry);

              if (fileEntry.getFileListener() != null) {
                fileEntry.getFileListener().fileChanged(fileEntry);
              } else {
                // Notify listeners
                for (Iterator<WeakReference<FileListener>> j =
                    listeners_.iterator(); j.hasNext(); ) {
                  WeakReference<FileListener> reference =
                      (WeakReference<FileListener>) j.next();
                  FileListener listener = (FileListener) reference.get();

                  // Remove from list if the back-end object has been GC'd
                  if (listener == null) {
                    j.remove();
                  } else {
                    listener.fileChanged(fileEntry);
                  }
                }
              }
            }
          } catch (Throwable t) {
            if (file != null) {
              t.printStackTrace();
              System.out.println(
                  "file monitor execute error, file=" + file.getAbsolutePath() +
                      t.getMessage());
            } else {
              System.out.println(
                  "file monitor execute error, file=null" + t.getMessage());
            }
          }
        }
      } catch (Throwable t) {
        System.out.println("执行文件监控发生错误" + t.getMessage());
      }
    }
  }
}
package com.yx.demo.filemonitor;

/**
 * FileListener
 *
 * @author yx
 * @date 2019/12/21 0:55
 */
public interface FileListener {
 /**
 *
 * @param fileEntry
 */
 public void fileChanged(FileEntry fileEntry);
}

package com.yx.demo.filemonitor;

import java.io.File;
import java.lang.ref.WeakReference;
/**
 * FileEntry
 * 文件Entry,如果FileEntry指定了FileListener,那么当文件发生变动时只触发指定的FileListener
 *
 * @author yx
 * @date 2019/12/21 0:56
 */
public class FileEntry {
  String id;
  File file;
  long lastModified;
  FileListener fileListener = null;
  Object userData;
  WeakReference<Object> reference = null;
  /**
   * 构造函数。
   *
   * @param id
   * @param file
   */
  public FileEntry(String id, File file) {
    this(id, file, file.exists() ? file.lastModified() : -1);
  }
  public FileEntry(Object reference, String id, File file) {
    this(id, file, file.exists() ? file.lastModified() : -1);
    reference = new WeakReference<Object>(reference);
  }
  /**
   * 构造函数。
   *
   * @param id      标识
   * @param file     要监控的文件
   * @param lastmodified 最后修改日期
   */
  public FileEntry(String id, File file, long lastmodified) {
    super();
    this.id = id;
    this.file = file;
    this.lastModified = lastmodified;
  }
  public boolean check() {
    if (reference != null && reference.get() == null) {
      //监控对象已经不存在,请求FileMonitor删除自己
      return false;
    }
    long newModifiedTime = file.exists() ? file.lastModified() : -1;
    if (lastModified != newModifiedTime) {
      this.lastModified = newModifiedTime;
      FileListener ls = this.getFileListener();
      if (ls == null) {
        return false;
      } else {
        try {
          ls.fileChanged(this);
        } catch (Exception e) {
          e.printStackTrace();
          System.err.println("执行文件监控事件监听" + e.getMessage());
        }
        return true;
      }
    } else {
      return true;
    }
  }
  public String getId() {
    return id;
  }
  public void setId(String id) {
    this.id = id;
  }
  public File getFile() {
    return file;
  }
  public void setFile(File file) {
    this.file = file;
  }
  public long getLastModified() {
    return lastModified;
  }
  public void setLastModified(long lastModified) {
    this.lastModified = lastModified;
  }
  public FileListener getFileListener() {
    return fileListener;
  }
  public void setFileListener(FileListener fileListener) {
    this.fileListener = fileListener;
  }
  public Object getUserData() {
    return userData;
  }
  public void setUserData(Object userData) {
    this.userData = userData;
  }
}

使用demo:

// 文件路径
String fileName = "conf/database.xml";
// 文件监控
FileListener fileListener = new FileListener() {
@Override
public void fileChanged(FileEntry fileEntry) {
// TODO 文件变化后的业务处理
}
};
File file = new File(fileName);
FileEntry fileEntry = new FileEntry("database", file);
// 设置文件监控
fileEntry.setFileListener(fileListener);
FileMonitor.getDefaultFileMonitor().addFileEntry(fileEntry);

总结

以上所述是小编给大家介绍的Java实现文件监控器FileMonitor的实例代码,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对我们网站的支持!
如果你觉得本文对你有帮助,欢迎转载,烦请注明出处,谢谢!

(0)

相关推荐

  • Java实现文件监控器FileMonitor的实例代码

    应用场景: 代码可以实现文件变化后的监听,如文件变化,自动重新加载文件内容,实现配置文件的热部署. 代码: package com.yx.demo.filemonitor; import java.io.File; import java.lang.ref.WeakReference; import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; import java.util.Iterat

  • java 实现文件夹的拷贝实例代码

    java 实现文件夹的拷贝实例代码         这里就直接上代码,废话不多说,很简单很实用. 实例代码: import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; public class CopyFile { public static void copy(String sourceFile , Str

  • Java与WebUploader相结合实现文件上传功能(实例代码)

    之前自己写小项目的时候也碰到过文件上传的问题,没有找到很好的解决方案.虽然之前网找各种解决方案的时候也看到过WebUploader,但没有进一步深究.这次稍微深入了解了些,这里也做个小结. 简单的文件和普通数据上传并保存 jsp页面: <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!DOCTYPE h

  • java向文件中追加内容与读写文件内容源码实例代码

    java向文件中追加内容与读写文件内容源码实例代码 向文件尾加入内容有多种方法,常见的方法有两种: RandomAccessFile类可以实现随机访问文件的功能,可以以读写方式打开文件夹的输出流 public void seek(long pos)可以将读写指针移到文件尾,参数Pos表示从文件开头以字节为单位测量的偏移位置,在该位置文件指针. public void write(int pos)将数据写到读写指针后面,完成文件的追加.参数pos表示要写入的Byte 通过FileWrite打开文件

  • Java防止文件被篡改之文件校验功能的实例代码

    1.为什么要防止文件被篡改? 答案是显然的,为了保证版权,系统安全性等.之前公司开发一个系统,技术核心是一个科学院院士的研究成果,作为一款商业软件来说,保证公司及作者版权是非常重要的.系统安全性就更不用说了,系统两三下就被搞垮了,那这个系统就不算是一个合格的系统. 2.文件校验和作用 我们都知道,一个系统或者软件都是由众多文件组成的.文件校验和的作用就是保证系统版本的正确性和唯一性.具体原理下面会详细解释. 3.文件校验和的原理 思路和实现的方式可能多种多样,我说的是自己的思路和实现方式,请读者

  • JAVA获取当前项目和文件所在路径的实例代码

    直接上代码: //当前项目下路径 File file = new File(""); String filePath = file.getCanonicalPath(); System.out.println(filePath); //当前项目下xml文件夹 File file1 = new File(""); String filePath1 = file1.getCanonicalPath()+File.separator+"xml\\";

  • BootStrap fileinput.js文件上传组件实例代码

    1.首先我们下载好fileinput插件引入插件 <span style="font-size:14px;"><link type="text/css" rel="stylesheet" href="fileinput/css/fileinput.css" rel="external nofollow" /> <script type="text/javascript

  • Java thrift服务器和客户端创建实例代码

    Thrift是一个软件框架,用来进行可扩展且跨语言的服务的开发.它结合了功能强大的软件堆栈和代码生成引擎,以构建在 C++, Java, Python, PHP, Ruby, Erlang, Perl, Haskell, C#, Cocoa, JavaScript, Node.js, Smalltalk, and OCaml 等等编程语言间无缝结合的.高效的服务. Thrift最初由facebook开发,07年四月开放源码,08年5月进入apache孵化器.thrift允许你定义一个简单的定义文

  • commons fileupload实现文件上传的实例代码

    一.文件上传的原理分析 1.文件上传的必要前提 a.表单的method必须是post b.表单的enctype属性必须是multipart/form-data类型的. enctype默认值:application/x-www-form-urlencoded 作用:告知服务器,请求正文的MIME类型 application/x-www-form-urlencoded : username=abc&password=123 ServletRequest.getParameter(String nam

  • 三种Java打印PDF文档的实例代码

    以下内容归纳了通过Java程序打印PDF文档时的3种情形.即: 1 静默打印 2 显示打印对话框打印 3 打印PDF时自定义纸张大小 使用工具:Spire.PDF for Java Jar文件获取及导入: 方法1:下载jar包.下载后,解压文件,并将lib文件夹下的Spire.Pdf.jar导入java程序. 方法2:可通过maven库导入.参考导入方法. Java代码示例 [示例1]静默打印 即通过使用默认打印机直接打印PDF文档.打印时,我们可以设置打印份数,设置纸张打印页边距等. impo

随机推荐