读取文件时BufferedReader会阻塞吗?

时间:2013-11-11 08:41:30

标签: java io block

我想使用“BufferedReader”来读取实时日志文件,并将新添加的内容打印到控制台:

File logfile = new File("logFile.txt");
BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream(logfile)));
while(true) {
    String line = reader.readLine();
    System.out.println(line);
    Thread.sleep(1000L);
}

它将打印新添加的行,有时会打印null(表示没有新行添加到日志中)。

我的问题是,reader.readLine()是否会在某些情况下被阻止?在我的测试中,它不会阻止,但我不确定它是否总是存在。

3 个答案:

答案 0 :(得分:2)

  

我的问题是,在某些条件下是否会阻止reader.readLine()

如果您正在读取的文件是本地文件系统中的常规文件,则不太可能会阻塞相当长的时间。实际上,如果必须等待从光盘读取数据,它根本就可能会阻塞。阻塞时间可能是10毫秒的数量级。

如果文件是远程安装的文件系统,则可能会出现严重延迟。实际上,在某些情况下,延误可能是无限期的;例如在重新启动远程服务器之后使用远程NFS安装(取决于安装选项...)。

如果文件是某种类型的“特殊文件”(例如磁带驱动器),那么也可能存在显着的延迟。 (套接字和管道流也将阻塞,但这与您的示例代码无关。)


在正常情况下,在测试用例中很难使读取被可靠地阻塞。


您似乎正在尝试实现一个不断读取写入日志文件末尾的行的类或方法。现有的课程可以做到这一点;例如Apache commons Tailer类。我建议您重复使用Tailer或类似的东西,而不是重新发明轮子。

答案 1 :(得分:1)

是的,它会阻塞,但不会有明显的时间间隔,除非您说是从网络驱动器读取并且网络发生了奇怪的事情。具有动态生成器的管道是另一个例子。

  

在我的测试中,它不会阻止

它不会阻止EOF,这可能是你真正想知道的。怎么可能呢?

  

将打印null(表示没有新行添加到日志中)

这意味着您已尝试阅读过去的EOF。

读取自己的日志文件的系统对我来说有一种非常难闻的气味。如果您需要系统与自身通信,实现它。

答案 2 :(得分:1)

由于您正在从阻塞FileInputStream读取,因此当操作系统从永久存储中读取数据时,执行将阻塞很短的时间。即使文件存储在本地磁盘上,也必须旋转磁盘并且必须将读取头移动到正确的位置,这需要时间,因为两者都是物理对象,并且在此期间您的程序除了等待之外什么都不做

readLine方法在到达文件末尾时返回null。当发生这种情况时,您要做的就是等待文件更新,然后尝试阅读更多内容:

while(true) {
    String line = reader.readLine();
    if (line == null) {
        Thread.sleep(1000L);
        continue;
    }
    System.out.println(line);
}

实际上这也不完美,因为如果日志文件的最后一行不完整readLine会返回它,当外部进程写完该行的其余部分时,您将通过单独调用{{{ 1}}。净效应:某些行可能会在输出中分割。