我有一个进程(实际上是一个网络服务器),它作为来自客户端的POST写入日志文件。
然后我有一个单独的进程在循环中读取日志文件,如(tail -f):
BufferedReader reader = new BufferedReader(new FileReader(logFilePath));
String line = null;
while (true)
{
if ( (line = reader.readLine()) != null )
{
if (firstLine == null) firstLine = line;
processLine(line);
continue;
}
try
{
Thread.sleep(sleepTime);
long ts = System.currentTimeMillis();
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
break;
}
}
这种方法在99%的时间内都能正常工作,但有时,我通过BufferedReader.readLine读取的行不是一个完整的行。我想这是因为编写器(网络服务器)还没有完成将该行的所有字节刷新到文件中。
有任何修复或解决此问题的建议吗?非常感谢!
答案 0 :(得分:1)
在处理需要几乎同时访问一个文件的多个进程(通常是一个接一个的进程)之后,我发现(和我一起工作的其他开发人员)一个“预告片”文件是很好用来指示一个进程何时完成与另一个进程需要访问的文件进行交互。
我不确定您的网络服务器写入此日志的频率以及您的Java进程需要多快读取它,但是如果每个进程访问该文件之间有时间可能会失效,则可以编写预告片文件out表示您的网络服务器何时完成写入文件。您的Java进程可以首先检查预告片文件是否存在,然后在找到它,删除然后从日志中读取。
否则,您可能需要使用操作系统命令来确定您的网络服务器是否正在写入日志,而只有在没有时才运行日志阅读器。 http://blog.bensmann.com/executing-operating-system-commands有一些关于用Java执行OS命令的好信息。
底线是否需要建立某种可靠的间隙,以便这些进程不会同时读取/写入日志。
答案 1 :(得分:-1)
我最近遇到了同样的问题,让我解释缓冲区读取器何时读取不完整的行与readline() 方法。它会在回车之前遇到EOF时执行此操作。
bufferedreader readine中的代码就像这样
if (nextChar >= nChars)
fill();
if (nextChar >= nChars) { /* EOF */
if (s != null && s.length() > 0)
return s.toString();
else
return null;
}
其中说如果在回车之前遇到EOF,它将返回已经读过的内容。 但正确的代码应该是当我们调用readLine()并且在回车之前遇到EOF字符时它应该返回NULL而不是不完整的行。
我编写了我的扩展bufferedreader类,其中ReadLine在上面解释的场景中返回NULL。