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万+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章