Java 代碼實現 tail -f

Java 利用定時實現 tail -f 功能

RandomAccessFile

可以指定位置讀,指定位置寫。

  • getFilePointer():獲取當前文件的記錄指針位置
  • seek(long pos):把記錄指針移動 pos 處

構造方法:

RandomAccessFile raf = new RandomAccessFile(File file, String mode);

mode 取值:

" r ":可讀

" w ":可寫

" r w":可讀可寫

實現原理:

利用 RandomAccessFile 類來讀取文件,在代碼中記錄當前文件的大小,也就是通過 getFilePointer() 獲取文件讀取結束的位置,下一次讀取時,從這個位置開始讀,保證了每次讀取只讀取新的內容。

存放文件讀取結束的位置,需要通過一個全局變量來存放,測試時就用 static 變量實現,實際項目使用,可以在數據庫中建張表存放。

實現代碼:

存放全局變量的類:

public class StaticConst {
    public static long filePointer = 0;
    
    public static long getFilePointer() {
        return filePointer;
    }
    public static void setFilePointer(long filePointer) {
        StaticConst.filePointer = filePointer;
    }
}

實現類:

public class BLogFileTailer extends Thread{

    private File logfile; // 文件對象

    // 構造函數
    public BLogFileTailer(File file) { this.logfile = file; }

    public void run() {
        long filePointer = StaticConst.getFilePointer();
        try {
            RandomAccessFile file = new RandomAccessFile(logfile, "r");
            long fileLength = this.logfile.length(); // 新文件的長度

            // 新文件的長度小於上一次讀取文件的長度時,從頭開始讀
            if (fileLength < filePointer) {
                filePointer = 0;
                StaticConst.setFilePointer(filePointer);
            }

            // 新文件長度大於上一次讀取文件的長度時
            // 通過 FilePointer 從上一次讀取文件的結尾開始讀
            if (fileLength > filePointer) {
                // RandomAccessFile.seek():表示從文件的第幾個位置開始搜索
                file.seek(filePointer);
                String line = file.readLine();
                while (line != null) {
                    // 過濾掉:當讀取到換行符 '/n' 的時候,會讀取到一行的內容爲空字符串
                    if("".equals(line)){
                        line = file.readLine();
                        continue;
                    }
                    System.out.println(line);
                    line = file.readLine(); // 讀取下一行數據
                }
                // RandomAccessFile.getFilePointer():記錄文件指針
                filePointer = file.getFilePointer();
                // 存放到全局變量中
                StaticConst.setFilePointer(filePointer);
            }
            file.close();
        } catch (IOException e) {
			// 異常信息
        }
    }
}

測試類:

@Test
public void testTailB() {
    // 測試代碼時,利用 for 循環配合 Thread.sleep() 模擬定時器的效果
    for (int i = 0; i < 5; i++) {
        Thread t = new Thread();
        try {
            BLogFileTailer tailer = new BLogFileTailer(new File("e:/test.txt"));
            tailer.run();
            t.sleep(5000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}
發佈了85 篇原創文章 · 獲贊 218 · 訪問量 45萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章