两(多个)个进程读取同一个Log文件

需求:

公司想开发一个系统日志管理系统——能够通过自己开发的系统能够查看其监视系统的日志

被监听的系统日志是单独运行的,每时每刻都会添加自己的日志,会往系统中写日志,那么我们开发的日志系统就会去读取其正在写的日志

问题:

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到文件中,因为读的进程是无法读取内存(缓存)中的内容的,只能读取磁盘中的文件内容

猜你喜欢

转载自hbiao68.iteye.com/blog/2021134