【问题标题】:Java file tailer implementationJava文件尾部实现
【发布时间】:2016-05-25 16:21:38
【问题描述】:

实现一个相当于tail -f somefile的java文件观察器

我读过一些类似的问题。我已经看到了一些选择。

  1. 使用BufferedReader,基本思想是使用缓冲读取器从文件中读取。如果返回 null 然后休眠几秒钟,然后继续无限循环。我对此进行了一些实验,我的结果显示只要你读到文件末尾,那么getLine方法将不再给你任何更新。那么这种方法是否有效?

  2. 使用random access file。每次进行读取操作时,创建一个随机访问文件,并将文件长度与历史文件长度进行比较,如果当前文件较长,则寻求最后一次读取并在增量部分中读取。我确定这可行,但是每次读取时都会打开一个新的随机访问文件,难道没有更有效的方法吗?

  3. 我看到新的 JDK 在缓冲文件阅读器中添加了stream API,我想这与尾部附加的新内容无关。它只与最初给出的内容有关。我的问题是可以扩展这个流 api 以考虑 tailer function 吗?

问题:

  • BufferedReader 可以用来实现tail -f 吗?在我的情况下,一旦我读取通过 EOF,只会返回 null。

  • JDK8 stream可以用来实现tail -f吗?

  • 除了像apache common lib这样反复打开关闭文件,还有没有更高效的实现方式?

【问题讨论】:

  • 1 和 3 可能是最简单的,实际上它只是您的选择。如果您已经看到所有这些的实现,为什么要问?只需选择最吸引您的一个。我个人是用 groovy 做的。我用 def text=new File("tailFile.txt").text.split() 或类似的东西阅读了整个文件——你可以从你想要的“文本”中选择任何行。非常简单,如果内存不足我会重新编写它(到目前为止我还没有,因为我没有拖尾任何 10gb 文件。
  • ps,。您的问题被表述为命令。您是要我们选择其中一个选项还是给您一个完整的实现?
  • @BillK 正如我在选项 1/3 中所说,它是否有效?就我而言,读到最后,根本没有返回任何新内容。
  • 您的BufferedReader 代码有问题。 BufferedReader 不保留读取之间的 EOF 状态。如果随后附加了数据,readLine() 可以读取超出返回 NULL 的点。测试了很多次。

标签: java file io


【解决方案1】:

我最终使用了一些 Apache 库来解决这个问题。 (我记得会更新)。

基本上,文件观察程序依赖于文件系统 API。在 linux 发行版上,阅读 EOF 可能会很好,并带来稍后附加的新内容。

我观察到的问题是在 MACO 上,一旦您在 EOF 之后阅读该文件处理程序就不再有效。如果您知道您正在阅读新内容,则必须重新打开该文件。

  • 这是在 MacOs Maveriks 上的,我没有测试它在最新版本上仍然相同。
  • 这也是基于 JDK api,而不是底层 MACOS 文件系统 API。因为我觉得 less /F tail -f 应该更有效地实施。

【讨论】:

    【解决方案2】:

    我前一阵子这样做了,根据我的经验,我猜你的问题可能没有实际意义——在读取之间关闭文件或使用 Apache Tailer 类可能会更好,因为有人从我的类似问题中建议:

    How can I follow a file like "Tail -f" does in Java without holding the file open (Prevent rename/delete)

    这不仅因为它可以帮助您刷新,而且可以防止文件在您阅读时被锁定。

    我最终没有使用它(因为在我的环境中获得批准的软件具有挑战性)——相反,我选择使用这样的流程:

    Detect Change
    Open file
    Seek to previous position
    Read to end of file
    Remember position for next seek
    Close 
    

    这个预制件非常好,解决了很多问题——我已经使用了一段时间了。

    该链接问题中的某人建议使用 java.nio.file.WatchService.poll() 来检测有效的更改 - 但重复读取文件大小也是如此。

    您在 #2 中提到了这种打开/查找/关闭方法——不要担心性能,因为与等待文件更新相比,打开/尾/关闭部分将花费很少的时间。如果您想要更高的效率,请在文件大小测试之间添加更长的延迟。这样会一次分出更多行,但会减少读取文件的频率。

    查看我的代码,我最终使用了具有位置设置方法的 FileChannel (FileInputStream.getChannel())。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-09-18
      • 2014-01-18
      • 1970-01-01
      • 2019-04-07
      • 1970-01-01
      • 2022-07-07
      相关资源
      最近更新 更多