1

我正在尝试实现一个日志拖尾,它将在前一个文件被删除并被新文件(永远)替换后继续拖尾。所以,每次我们重新启动服务器(打印日志)时,我都不必运行这个程序。

这是我的代码。

public void tail(String file) throws InterruptedException, IOException {
    waitUntilFileExist(file);

    File f = new File(file);

    BufferedReader br = new BufferedReader(new FileReader(file.trim()));

    br.skip(f.length());
    String line = null;

    while (f.exists()) {

       f = new File(file);
        line = br.readLine();

        if (line == null) {

            Thread.sleep(1000);

        } else {
            if (msl != null) {
               //Send line to attached interface
                msl.onMessage(line);
            }
        }

    }

   waitUntilFileExist(file);

    tail(file);


}

public void waitUntilFileExist(String file) throws InterruptedException {
    File f = new File(file);
    if (!f.exists()) {
        System.out.println("File doesn't exists");
        Thread.sleep(1000);
        waitUntilFileExist(file);
    } else {
        System.out.println("File does exists");
    }
}

首先,它会检查指定的文件是否存在?虽然它确实存在,但读取文件并打印该行。如果文件在读取过程中被删除,它会等到文件被重新创建后再调用tail方法。

我在 Linux 机器上对此进行了测试,它工作正常,但我不确定这是否是正确的方法。你有其他方法可以做到这一点吗?这适用于几天和几个月的生产环境吗?

4

1 回答 1

0

tail您的程序将因堆栈溢出错误而失败,因为每次您在方法和中使用递归方法调用越来越深入waitUntilFileExist,并且永远无法摆脱它们。我对您的代码做了更好的变体:

public void tail(String file) throws InterruptedException, IOException {
    boolean isNeedRun = true;
    while (isNeedRun) {
        waitUntilFileExist(file);
        try {
            readFile(file);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

private void readFile(String file) throws InterruptedException, IOException {
    File f = new File(file);

    FileReader reader = new FileReader(file.trim());
    try {
        BufferedReader br = new BufferedReader(reader);
        br.skip(f.length());
        String line;

        while (f.exists()) {

            f = new File(file);
            line = br.readLine();

            if (line == null) {

                Thread.sleep(1000);

            } else {
                if (msl != null) {
                    //Send line to attached interface
                    msl.onMessage(line);
                }
            }
        }
    } finally {
        try {
            reader.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

private void waitUntilFileExist(String file) throws InterruptedException {
    File f = new File(file);
    while (!f.exists()) {
        System.out.println("File doesn't exists");
        Thread.sleep(1000);
    }
    System.out.println("File does exists");
}

但是这个变种也不完美!您可能会丢失一些行,因为可能会在行waitUntilFileExist(file);br.skip(f.length());.

如果您在 unix 系统上需要 tail,最好使用tail控制台工具。您可以从 java 启动单独的进程并使用它的输出。当文件被删除并再次创建时,此变体将保证 0% 的损失。

于 2012-08-16T16:53:52.420 回答