兩(多個)個程序讀取同一個Log檔案
阿新 • • 發佈:2019-01-31
需求:
公司想開發一個系統日誌管理系統——能夠通過自己開發的系統能夠檢視其監視系統的日誌
被監聽的系統日誌是單獨執行的,每時每刻都會新增自己的日誌,會往系統中寫日誌,那麼我們開發的日誌系統就會去讀取其正在寫的日誌
問題:
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到檔案中,因為讀的程序是無法讀取記憶體(快取)中的內容的,只能讀取磁碟中的檔案內容。