1. 程式人生 > >兩(多個)個程序讀取同一個Log檔案

兩(多個)個程序讀取同一個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到檔案中,因為讀的程序是無法讀取記憶體(快取)中的內容的,只能讀取磁碟中的檔案內容