There is a log file that is constantly updated with logs. The file size can reach several hundred megabytes. I do not want to read the file completely every time, since it takes a lot of time. It is necessary to make the data reading mechanism in such a way that the reader is spinning in a separate stream, and I could get the actual logs at any time.
3 answers
import java.io.File; import java.io.RandomAccessFile; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; public class Tailer implements Runnable { private File file; private int runEvery; private long lastPosition = 0; private boolean run = true; public Tailer(String inputFile, int interval) { file = new File(inputFile); this.runEvery = interval; } public void stop() { run = false; } public void run() { try { while(run) { Thread.sleep(runEvery); long fileLength = file.length(); if(fileLength > lastPosition) { RandomAccessFile fh = new RandomAccessFile(file, "r"); fh.seek(lastPosition); byte c; while((c = (byte)fh.read()) != -1) { System.out.print((char)c); } lastPosition = fh.getFilePointer(); fh.close(); } } } catch(Exception e) { stop(); } } public static void main(String argv[]) { ExecutorService executor = Executors.newFixedThreadPool(4); Tailer tailer = new Tailer("test.log", 1000); executor.execute(tailer); } } - better already), it’s more like it - Senior Pomidor
- So it can be noted as a solution;) - Sergey Gornostaev
|
I believe that you need Stream, with getting a position. You can use the .skip () method on the stream and skip the first bytes that you have already extracted from the file. Sketched a simple class
class Worker { Logger logger = new Logger(); public void DoSomeWork() { //Запускаем логгер в отдельном потоке Thread logThread = new Thread(logger); logThread.start(); //Какая то работа // // // //Остановить логгер logger.flag = false; } } //Класс логгера, имплементируем Runnable, чтобы получить возможность запускать логгер в отдельном потоке class Logger implements Runnable { //Текущая позиция в нашем файле private long currentPosition; private FileInputStream fis = null; private BufferedReader reader = null; //Используем, чтобы остановить логгнр public boolean flag = true; @Override public void run() { fis = new FileInputStream("C:/sample.txt"); reader = new BufferedReader(new InputStreamReader(fis)); while(flag) { try { //Можно вызывать reader.skip(currentPosition);, чтобы пропустить прочитанные байты String line = reader.readLine(); WriteLog(line); //Записываем текущую позицию потока, можем использовать позицию где угодно, развивая наш логгер currentPosition = fis.getChannel().position(); //Симулируем логгинг каждую секунду Thread.sleep(1000); } catch (IOException e) { e.printStackTrace(); } catch (InterruptedException e) { e.printStackTrace(); } } } public void WriteLog(String message) { //Здесь выводите сообщение куда угодно, например System.out.printf(message); } } |
Here is how I implemented it. Singleton class
package main.java.services; import main.java.utils.*; import javax.imageio.stream.*; import java.io.*; import static java.lang.Thread.sleep; public class LogFileService{ private static boolean running = true; private static File fileName; private static BufferedInputStream reader; private static StringBuilder stringBuilder; private static LogFileService instance = null; public LogFileService() throws FileNotFoundException { fileName = new File("C:\\log.log"); reader = new BufferedInputStream(new FileInputStream( fileName ) ); stringBuilder = new StringBuilder(); this.instance = this; } private void run() { while( running ) { try { if( reader.available() > 0 ) { stringBuilder.append( (char)reader.read() ); } else { try { sleep( 500 ); } catch( InterruptedException ex ) {} } } catch (IOException e) { running = false; } } } public static void start(){ Thread t = new Thread(() -> { LogFileService.getInstance().run(); }); t.start(); } public static LogFileService getInstance() { if(instance == null) { try { instance = new LogFileService(); } catch (FileNotFoundException e) { Messages.getInstance().error(fileName.getAbsolutePath() + " not found", e); } } return instance; } public static StringBuilder getLog(){ return stringBuilder; } } |