我需要能够用 Java 模仿
tail -f
。我试图读取另一个进程正在写入的日志文件,但是当我打开文件来读取它时,它会锁定该文件,并且其他进程无法再写入它。任何帮助将不胜感激!
这是我当前正在使用的代码:
public void read() {
Scanner fp = null;
try {
fp = new Scanner(new FileReader(this.filename));
fp.useDelimiter("\n");
} catch (java.io.FileNotFoundException e) {
System.out.println("java.io.FileNotFoundException e");
}
while (true) {
if (fp.hasNext()) {
this.parse(fp.next());
}
}
}
由于文件截断和(中间)删除等特殊情况,重建 tail 很棘手。要在不锁定的情况下打开文件,请使用
StandardOpenOption.READ
和新的 Java 文件 API:
try (InputStream is = Files.newInputStream(path, StandardOpenOption.READ)) {
InputStreamReader reader = new InputStreamReader(is, fileEncoding);
BufferedReader lineReader = new BufferedReader(reader);
// Process all lines.
String line;
while ((line = lineReader.readLine()) != null) {
// Line content content is in variable line.
}
}
对于我在 Java 中创建尾部的尝试,请参阅:
examineFile(…)
queue.feed(lineContent)
传递行内容供听众处理,并且等于您的
this.parse(…)
。
此处。要锁定文件,您可以检查此处
java.io 为您提供强制文件锁,而 java.nio 为您提供 咨询文件锁如果你想在没有任何锁定的情况下读取任何文件,你可以使用下面的类
import java.nio.channels.FileChannel;
import java.nio.file.Paths;
如果您想逐行尾部文件,请使用以下代码
public void tail(String logPath){
String logStr = null;
FileChannel fc = null;
try {
fc = FileChannel.open(Paths.get(logPath), StandardOpenOption.READ);
fc.position(fc.size());
} catch (FileNotFoundException e1) {
System.out.println("FileNotFoundException occurred in Thread : " + Thread.currentThread().getName());
return;
} catch (IOException e) {
System.out.println("IOException occurred while opening FileChannel in Thread : " + Thread.currentThread().getName());
}
while (true) {
try {
logStr = readLine(fc);
if (logStr != null) {
System.out.println(logStr);
} else {
Thread.sleep(1000);
}
} catch (IOException|InterruptedException e) {
System.out.println("Exception occurred in Thread : " + Thread.currentThread().getName());
try {
fc.close();
} catch (IOException e1) {
}
break;
}
}
}
private String readLine(FileChannel fc) throws IOException {
ByteBuffer buffers = ByteBuffer.allocate(128);
// Standard size of a line assumed to be 128 bytes
long lastPos = fc.position();
if (fc.read(buffers) > 0) {
byte[] data = buffers.array();
boolean foundTmpTerminator = false;
boolean foundTerminator = false;
long endPosition = 0;
for (byte nextByte : data) {
endPosition++;
switch (nextByte) {
case -1:
foundTerminator = true;
break;
case (byte) '\r':
foundTmpTerminator = true;
break;
case (byte) '\n':
foundTmpTerminator = true;
break;
default:
if (foundTmpTerminator) {
endPosition--;
foundTerminator = true;
}
}
if (foundTerminator) {
break;
}
}
fc.position(lastPos + endPosition);
if (foundTerminator) {
return new String(data, 0, (int) endPosition);
} else {
return new String(data, 0, (int) endPosition) + readLine(fc);
}
}
return null;
}
CreateFile
带有共享标志
FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE
的句柄。这在 JDK 内部的一些地方用于打开文件以读取属性和内容,但据我所知,它没有导出/可用到 Java 类库级别。所以你需要找到一个本地库来做到这一点。
我认为作为一种快速解决方法,您可以从命令
process.getInputStream()
"cmd /D/C type file.lck"