【问题标题】:How to read a text file in real time with Java ON LINUX?如何使用 Java ON LINUX 实时读取文本文件?
【发布时间】:2015-11-10 11:18:32
【问题描述】:

我将“ON LINUX”放在大写字母中不是为了惹恼你,而是因为我已经能够在 Windows 上使用 3 个不同的文件读取类来做到这一点。 文件输入流 缓冲阅读器 随机存取文件 (我确定最后两个,但第一个可能是错误的 - 我的记忆是baaad。)所有这些都在我的Windows上完美运行。 我对这些阅读器的预期用途是实时逐行读取文本文件,这意味着,当保存该文件的新版本并附加新行时,Java 程序会读取该行,并对其进行处理并然后继续检查另一个新行。

我尝试使用 Java 7 openJDK、Java 7 Oracle 和 Java 8 Oracle 环境进行编译,所有生成的 .jar 在 Windows 上都可以正常工作,而且由于 Java 是跨平台的,我认为它们也可以在 Linux 上工作(对吗?) ,但是我编译的每个版本在 linux 上测试时都失败了。 运行 linux Red Hat 的社区论坛成员引起了我的注意,没有错误/异常,看起来它正在运行,但只是没有工作。我今天安装了 Ubuntu 并亲自尝试:读者会很好地阅读原始文件,但不会实时“流式传输”文件。对文件的更改不会被注意到。 我很困惑这是怎么可能的,老实说,我很惊讶它没有在任何地方提出(据我所知,哈哈)。希望这意味着我在确保有人可能追踪的 linux 兼容性方面犯了一个愚蠢的错误。 感谢任何和所有帮助/答案/解决方法!

这是我尝试在我的程序中实现的代码示例:

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.RandomAccessFile;

public class Driver {

    public static void main(String[] args) {
        RandomAccessFile reader = null;
        try {
            reader = new RandomAccessFile(new File("/home/citats/csgo/console.log"), "r");
        } catch (FileNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        String currLine;
        Boolean done = false;
        while (!done) {
            try {
                if ((currLine = reader.readLine()) != null)
                {
                    System.out.println(currLine);
                    if (currLine.equals("done"))
                        done = true;
                } else
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
        reader.close();
    }
}

【问题讨论】:

  • 尝试使用较新的 NIO 类,因为它们可能提供对文件的更直接访问。较旧的 IO 类可能使用以只读方式打开文件的 Linux API,它可能正在访问文件的快照。 (我猜这里)。
  • 我必须在main 中添加一个throws Exception 来处理reader.close 周围缺少的try-catch,我还将您的路径更改为/tmp/abc.log。然后我做了一个touch /tmp/abc.log 并运行程序。最后,我做了一个echo test >>/tmp/abc.log,我确实看到了产生输出的程序。您能否提供重现问题的说明?
  • 在回显和使用 nano 通过 shell 写入文件时,我也看到了预期的输出。但是,当我使用 gedit 在日志中附加一行时,我看不到输出。很奇怪。我认为可以安全地假设正在写入日志文件的游戏控制台可能会遇到 gedit 遇到的相同问题,无论是什么问题!
  • 如果您对文件执行“cat”操作,您是否看到新行,而在您的程序中看不到它?
  • 罗伯托说的没错。

标签: java linux stream real-time compatibility


【解决方案1】:

拖尾文件

要获得像 tail -f 这样的功能,您的解决方案会在其中监视新文件更新,然后对其进行处理,请参阅以下答案:How can I follow a file like "Tail -f" does in Java without holding the file open (Prevent rename/delete)。其来源为您正在尝试的内容提供信息。我怀疑一些寻求解决了您所看到的问题。 Tailer Source

实现类似结果但功能更强大的另一种非常有趣的方法是使用 JavaRX 文件,您可以在其中安排新更改以使用 Java NIO 以更异步的方式交付。在他们的主页上有一个例子:RxJava file github page

import com.github.davidmoten.rx.FileObservable;
import rx.Observable;
import java.io.File; 

Observable<String> items = 
     FileObservable.tailer()
               .file("/var/log/server.log")
               .startPosition(0)
               .sampleTimeMs(500)
               .chunkSize(8192)
               .utf8()
               .tailText();

RxJava

有关为何使用 JavaRx 的更多信息,请参阅RxJava project

【讨论】:

    猜你喜欢
    • 2011-02-16
    • 1970-01-01
    • 2014-05-21
    • 2021-12-03
    • 1970-01-01
    • 2011-09-09
    • 2011-08-17
    • 1970-01-01
    • 2016-08-08
    相关资源
    最近更新 更多