gpt4 book ai didi

java - 如何使用java检查正在外部更新的文件的内容?

转载 作者:行者123 更新时间:2023-12-03 06:13:09 26 4
gpt4 key购买 nike

有一个 shell 脚本正在更新日志文件。

我想在写入日志文件时逐行显示日志(而不是一次显示整个文件)。

写入文件工作正常,但我在读取文件时遇到问题,因为它一次显示整个文件。

这是我的阅读代码:

String nmapstatusfile = runMT.instdir+"/logs/nmapout."+customer+".log";
String nmapcommand=runMT.instdir+"/bin/doscan.sh "+nmapoutfile+" "
+IPRange+" "+nmapstatusfile+" "+nmapdonefile;

System.out.println("nmapcommand is .. "+nmapcommand);
Runtime r = Runtime.getRuntime();
Process pr = r.exec(nmapcommand);
RandomAccessFile raf =null;
try {
System.out.println(nmapstatusfile);
System.out.println("Reading a file");
raf = new RandomAccessFile(nmapstatusfile, "r");
} catch (FileNotFoundException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
} // read from input file
System.out.println("Will print file contents line by line...");
long pos = 0;
raf.seek(pos);
String line =null;
while ((line = raf.readLine())!= null) {
System.out.println("in while loop for file read.");
System.out.println(line);
}
pos = raf.getFilePointer();
pr.waitFor();

我使用了RandomAccessFile,但一直无法得到想要的结果。

如何读取文件内容才能逐行显示?

最佳答案

这需要 Java 7,因为它在文件系统上注册一个观察程序,只要给定文件发生更改,该观察程序就会收到通知。它允许任意数量的读取器(使用同步来避免竞争条件)。

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.nio.file.ClosedWatchServiceException;
import java.nio.file.Path;
import java.nio.file.StandardWatchEventKinds;
import java.nio.file.WatchKey;
import java.nio.file.WatchService;
import java.util.ArrayDeque;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
* Reads lines from a file that is actively being updated by another process
*/
public class Tailer {
private static final Logger logger = Logger.getLogger("Tailer");

private long tooLateTime = -1;
private final long maxMsToWait;
private final File file;
private long offset = 0;
private int lineCount = 0;
private boolean ended = false;
private WatchService watchService = null;
ArrayDeque<String> lines = new ArrayDeque<>();

/**
* Allows output of a file that is being updated by another process.
* @param file to watch and read
* @param maxTimeToWaitInSeconds max timeout; after this long without changes,
* watching will stop. If =0, watch will continue until <code>stop()</code>
* is called.
*/
public Tailer(File file, long maxTimeToWaitInSeconds) {
this.file = file;
this.maxMsToWait = maxTimeToWaitInSeconds * 1000;
}

/**
* Start watch.
*/
public void start() {
updateOffset();
// listens for FS events
new Thread(new FileWatcher()).start();
if (maxMsToWait != 0) {
// kills FS event listener after timeout
new Thread(new WatchDog()).start();
}
}

/**
* Stop watch.
*/
public void stop() {
if (watchService != null) {
try {
watchService.close();
} catch (IOException ex) {
logger.info("Error closing watch service");
}
watchService = null;
}
}

private synchronized void updateOffset() {
tooLateTime = System.currentTimeMillis() + maxMsToWait;
try {
BufferedReader br = new BufferedReader(new FileReader(file));
br.skip(offset);
while (true) {
String line = br.readLine();
if (line != null) {
lines.push(line);
// this may need tweaking if >1 line terminator char
offset += line.length() + 1;
} else {
break;
}
}
br.close();
} catch (Exception ex) {
logger.log(Level.SEVERE, "Error reading", ex);
}
}

/**
* @return true if lines are available to read
*/
public boolean linesAvailable() {
return ! lines.isEmpty();
}

/**
* @return next unread line
*/
public synchronized String getLine() {
if (lines.isEmpty()) {
return null;
} else {
lineCount ++;
return lines.removeLast();
}
}

/**
* @return true if no more lines will ever be available,
* because stop() has been called or the timeout has expired
*/
public boolean hasEnded() {
return ended;
}

/**
* @return next line that will be returned; zero-based
*/
public int getLineNumber() {
return lineCount;
}

private class WatchDog implements Runnable {
@Override
public void run() {
while (System.currentTimeMillis() < tooLateTime) {
try {
Thread.sleep(1000);
} catch (InterruptedException ex) {
// do nothing
}
}
stop();
}
}

private class FileWatcher implements Runnable {
private final Path path = file.toPath().getParent();
@Override
public void run() {
try {
watchService = path.getFileSystem().newWatchService();
path.register(watchService, StandardWatchEventKinds.ENTRY_MODIFY);
while (true) {
WatchKey watchKey = watchService.take();
if ( ! watchKey.reset()) {
stop();
break;
} else if (! watchKey.pollEvents().isEmpty()) {
updateOffset();
}
Thread.sleep(500);
}
} catch (InterruptedException ex) {
logger.info("Tail interrupted");
} catch (IOException ex) {
logger.log(Level.WARNING, "Tail failed", ex);
} catch (ClosedWatchServiceException ex) {
// no warning required - this was a call to stop()
}
ended = true;
}
}

/**
* Example main. Beware: the watch listens on a whole folder, not on a single
* file. Any update on a file within the folder will trigger a read-update.
* @param args
* @throws Exception
*/
public static void main(String[] args) throws Exception {
String fn = args.length == 0 ? "/tmp/test/log.txt" : args[0];
Tailer t = new Tailer(new File(fn), 10);
t.start();
while ( ! t.hasEnded()) {
while (t.linesAvailable()) {
System.out.println(t.getLineNumber() + ": " + t.getLine());
}
Thread.sleep(500);
}
}
}

关于java - 如何使用java检查正在外部更新的文件的内容?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20797281/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com