需求:
公司想开发一个系统日志管理系统——能够通过自己开发的系统能够查看其监视系统的日志
被监听的系统日志是单独运行的,每时每刻都会添加自己的日志,会往系统中写日志,那么我们开发的日志系统就会去读取其正在写的日志
问题:
1、正在写的文件能否同时支持另外一个系统读取其中的内容? —— 能
2、如果能,如何实现获取想要的数据? —— 根据实际情况,研究算法
下面我写一个例子
写类
import java.io.FileWriter; import java.io.IOException; import java.io.PrintWriter; class Writer implements Runnable { Writer(String filename) { this.filename = filename; } private String filename; private int count = 0; @Override public void run() { while (count++ < 1000) { try { PrintWriter pw = new PrintWriter(new FileWriter(filename, true)); pw.append("" + count).append("\t").append("" + System.currentTimeMillis()).append("写入的内容").append("\r\n"); pw.close(); Thread.sleep(1000); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } }
读类
import java.io.BufferedReader; import java.io.File; import java.io.FileNotFoundException; import java.io.FileWriter; import java.io.IOException; import java.io.InputStreamReader; import java.io.PrintWriter; import java.io.RandomAccessFile; import java.io.ByteArrayInputStream; class Reader implements Runnable { Reader(String filename) { this.filename = filename; } private String filename; private long filelength = 0; private int count = 0; @Override public void run() { while (true) { try { File f = new File(filename); long nowlength = f.length(); long readlength = nowlength - filelength; if (readlength == 0) { Thread.sleep(1000); continue; } RandomAccessFile rf = new RandomAccessFile(f, "r"); // 移动文件指针到上次读的最后 rf.seek(filelength); filelength = nowlength; byte[] b = new byte[(int) readlength]; rf.read(b, 0, b.length); rf.close(); BufferedReader br = new BufferedReader(new InputStreamReader(new ByteArrayInputStream(b))); String str = null; count++; System.out.println("第" + count + "次读到的内容:"); while ((str = br.readLine()) != null) { System.out.println(str); } br.close(); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } public static void main(String[]args){ Reader reader = new Reader("/home/readfile/test.log"); new Thread(reader).start(); } }
测试类
public class ReadFileFromTrail { public static void main(String[] args) { Reader reader = new Reader("/home/readfile/test.log"); Writer writer = new Writer("/home/readfile/test.log"); // new Thread(reader).start(); new Thread(writer).start(); } }
备注:
1、测试上面的代码需要先运行ReadFileFromTrail类,再运行Reader,这种方式实际上说明的是两个进程访问同一文件(即不同的应用系统之间访问同一文件)
2、如果去掉ReadFileFromTrail类文件中的注释,则是不同的线程之间访问同一文件
上面的代码实际上是有要求的:
1、只能有一个写的进程,并且保证只会多不会少,否则读的进程就无法保证读取的长度是否有效
2、写的进程应该把写入缓存中的内容必须flush到文件中,因为读的进程是无法读取内存(缓存)中的内容的,只能读取磁盘中的文件内容。