Java订阅从大文件中读取新行

时间:2014-08-21 11:40:13

标签: java multithreading syslog

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

  1. 将不断检查该文件中是否出现了一些新数据
  2. 如果找到特定行,将执行特定操作
  3. 实现步骤1的最佳(有效)方法是什么?如何从文件中不断读取新行?

1 个答案:

答案 0 :(得分:0)

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

让我们调用文件currentFile

的这个实例

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

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

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

以下是检查更改的示例代码

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), ...);
    }
  }
}