【问题标题】:Java subscribing to read a new lines from a big fileJava订阅从大文件中读取新行
【发布时间】:2014-08-21 11:40:12
【问题描述】:

我想从我的 java 应用程序中读取 syslog 消息。我将查看文件/var/log/messages。 该文件可能很大。我想有一个线程:

  1. 它将不断检查该文件中是否出现了一些新数据
  2. 如果找到特定行将执行特定操作

实现第 1 步的最佳(有效)方法是什么。我怎样才能不断地从文件中读取新行?

【问题讨论】:

  • 你有什么要开始的吗?

标签: java multithreading syslog


【解决方案1】:

首次尝试检查更改时启动线程并获取文件的实例。这将是您的起点。现在使用 Java Diff Utility 检查您的文件是否添加了任何新行或文件中发生了任何类型的更改。

我们称这个文件实例为currentFile

您可以使用此实用程序继续检查新数据。

https://code.google.com/p/java-diff-utils/

Diff Utils 库是一个开源库,用于执行文本之间的比较操作:计算差异、应用补丁、生成统一差异或解析它们、生成差异输出以便于将来显示(如并排视图)等等.

这是检查更改的示例代码

import difflib.*;

public class BasicJavaApp_Task1 {
        // Helper method for get the file content
        private static List<String> fileToLines(String filename) {
                List<String> lines = new LinkedList<String>();
                String line = "";
                try {
                        BufferedReader in = new BufferedReader(new FileReader(filename));
                        while ((line = in.readLine()) != null) {
                                lines.add(line);
                        }
                } catch (IOException e) {
                        e.printStackTrace();
                }
                return lines;
        }

        public static void main(String[] args) {
                List<String> original = fileToLines("originalFile.txt");
                List<String> revised  = fileToLines("revisedFile.txt");

                // Compute diff. Get the Patch object. Patch is the container for computed deltas.
                Patch patch = DiffUtils.diff(original, revised);

                for (Delta delta: patch.getDeltas()) {
                        System.out.println(delta);
                }
        }
}

您可以使用Delta 来检查您正在寻找的特定数据。

现在由您来决定您希望比较发生的频率是多少。比如每 1000 毫秒,或者 10000 毫秒等等。

还要确保每次比较后你应该更新你的currentFile

对于第 2 步:为了发送回调您可以执行以下操作

使用ScheduleExecutorService

ScheduledExecutorService ses = Executors.newScheduledThreadPool(1);
void registerCallback() {
  ses.schedule(new MyCommand(), 30, TimeUnit.SECONDS);
}

它返回一个Future,如果您愿意,可以使用它来取消执行,或者获取MyCommand返回的值。

如果您想安排一个会按时重复的命令,您可以使用其他安排方法:scheduleAtFixedRatescheduleWithFixedDelay

如果您只需要在某些情况下或以不同的速率或间隔重新安排,我使用的一种技术是将ScheduledExecutorService 传递给您的命令(即new MyCommand(ses)) 并让它重新安排自己或新的具有适当延迟的命令:

class MyCommand implements Runnable {
  private final ScheduledExecutorService ses;
  MyCommand(ScheduledExecutorService ses) { this.ses = ses; }
  private boolean shouldReschedule() { ... }
  private int getRescheduleTimeoutMs() { ... }
  @Override void run() {
    // do work
    ...
    // reschedule if needed
    if (shouldReschedule()) {
      // reschedule this command:
      ses.schedule(this, getRescheduleTimeoutMs(), TimeUnit.MILLISECONDS);
      // or else a new one:
      ses.schedule(new MyCommand(ses), ...);
    }
  }
}

【讨论】:

  • 这不能回答 OP 的问题。
  • @TheLostMind 这些细节有帮助吗?
  • 我在想一些简单的事情 - 没有额外的库。是否有任何选项: 1. 保存读取的最后位置(字节数) 2. 注册回调函数,当文件中出现新数据时回调函数(类似于 Linux 中的信号?)?
  • 这个库以有效的方式完成了比较算法的繁重工作。是的,如果您在文件中找到某些内容,您可以注册一个处理程序或某事以将回调发布到您想要执行操作的线程。
  • Ishan:您能给我任何提示,当新数据附加到文件时如何注册该回调函数?我应该为此使用什么课程?
猜你喜欢
  • 1970-01-01
  • 2014-10-13
  • 2012-05-03
  • 2016-07-14
  • 2010-10-07
  • 1970-01-01
  • 1970-01-01
  • 2015-11-11
  • 2018-12-18
相关资源
最近更新 更多