最近在处理一个读取日志优化的问题,网上看到这个文章,感谢作者的仔细讲解,和大家共享一下,如下:


最近有一个银行数据漂白系统,要求操作人员在页面调用远端Linux服务器的shell,并将shell输出的信息保存到一个日志文件,前台页面要实时显示日志文件的内容.这个问题难点在于如何判断哪些数据是新增加的,通过查看JDK 的帮助文档,java.io.RandomAccessFile
可以解决这个问题.为了模拟这个问题,编写LogSvr和 LogView类,LogSvr不断向mock.log日志文件写数据,而 LogView则实时输出日志变化部分的数据.

代码1:日志产生类

Java代码  收藏代码

  1. package com.bill99.seashell.domain.svr;  

  2.   

  3. import java.io.File;  

  4. import java.io.FileWriter;  

  5. import java.io.IOException;  

  6. import java.io.Writer;  

  7. import java.text.SimpleDateFormat;  

  8. import java.util.Date;  

  9. import java.util.concurrent.Executors;  

  10. import java.util.concurrent.ScheduledExecutorService;  

  11. import java.util.concurrent.TimeUnit;  

  12. /** 

  13.  *<p>title: 日志服务器</p> 

  14.  *<p>Description: 模拟日志服务器</p> 

  15.  *<p>CopyRight: CopyRight (c) 2010</p> 

  16.  *<p>Company: 99bill.com</p> 

  17.  *<p>Create date: 2010-6-18</P> 

  18.  *@author Tank Zhang<tank.zhang@99bill.com> 

  19.  *@version v0.1 2010-6-18 

  20.  */  

  21. public class LogSvr {  

  22.       

  23.     private SimpleDateFormat dateFormat =   

  24.         new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");  

  25.   

  26.     /** 

  27.      * 将信息记录到日志文件 

  28.      * @param logFile 日志文件 

  29.      * @param mesInfo 信息 

  30.      * @throws IOException  

  31.      */  

  32.     public void logMsg(File logFile,String mesInfo) throws IOException{  

  33.         if(logFile == null) {  

  34.             throw new IllegalStateException("logFile can not be null!");  

  35.         }  

  36.         Writer txtWriter = new FileWriter(logFile,true);  

  37.         txtWriter.write(dateFormat.format(new Date()) +"\t"+mesInfo+"\n");  

  38.         txtWriter.flush();  

  39.     }  

  40.       

  41.     public static void main(String[] args) throws Exception{  

  42.           

  43.         final LogSvr logSvr = new LogSvr();  

  44.         final File tmpLogFile = new File("mock.log");  

  45.         if(!tmpLogFile.exists()) {  

  46.             tmpLogFile.createNewFile();  

  47.         }  

  48.         //启动一个线程每5秒钟向日志文件写一次数据  

  49.         ScheduledExecutorService exec =   

  50.             Executors.newScheduledThreadPool(1);  

  51.         exec.scheduleWithFixedDelay(new Runnable(){  

  52.             public void run() {  

  53.                 try {  

  54.                     logSvr.logMsg(tmpLogFile, " 99bill test !");  

  55.                 } catch (IOException e) {  

  56.                     throw new RuntimeException(e);  

  57.                 }  

  58.             }  

  59.         }, 05, TimeUnit.SECONDS);  

  60.     }  

  61. }  

 代码2:显示日志的类

 

 

Java代码  收藏代码

  1. package com.bill99.seashell.domain.client;     

  2.     

  3. import java.io.File;     

  4. import java.io.IOException;     

  5. import java.io.RandomAccessFile;     

  6. import java.util.concurrent.Executors;     

  7. import java.util.concurrent.ScheduledExecutorService;     

  8. import java.util.concurrent.TimeUnit;     

  9.     

  10. public class LogView {     

  11.     private long lastTimeFileSize = 0;  //上次文件大小     

  12.     /**   

  13.      * 实时输出日志信息   

  14.      * @param logFile 日志文件   

  15.      * @throws IOException   

  16.      */    

  17.     public void realtimeShowLog(File logFile) throws IOException{     

  18.         //指定文件可读可写     

  19.         final RandomAccessFile randomFile = new RandomAccessFile(logFile,"rw");     

  20.         //启动一个线程每10秒钟读取新增的日志信息     

  21.         ScheduledExecutorService exec =      

  22.             Executors.newScheduledThreadPool(1);     

  23.         exec.scheduleWithFixedDelay(new Runnable(){     

  24.             public void run() {     

  25.                 try {     

  26.                     //获得变化部分的     

  27.                     randomFile.seek(lastTimeFileSize);     

  28.                     String tmp = "";     

  29.                     while( (tmp = randomFile.readLine())!= null) {     

  30.                         System.out.println(new String(tmp.getBytes("ISO8859-1")));     

  31.                     }     

  32.                     lastTimeFileSize = randomFile.length();     

  33.                 } catch (IOException e) {     

  34.                     throw new RuntimeException(e);     

  35.                 }     

  36.             }     

  37.         }, 01, TimeUnit.SECONDS);     

  38.     }     

  39.          

  40.     public static void main(String[] args) throws Exception {     

  41.         LogView view = new LogView();     

  42.         final File tmpLogFile = new File("mock.log");     

  43.         view.realtimeShowLog(tmpLogFile);     

  44.     }     

  45.     

  46. }    

 

执行LogSvr类,LogSvr类会启动一个线程,每5秒钟向mock.log日志文件写一次数据,然后再执行LogView类,LogView每隔1秒钟读一次,如果数据有变化则输出变化的部分.

 

结果输出:

2010-06-19 17:25:54  99bill test !
2010-06-19 17:25:59  99bill test !
2010-06-19 17:26:04  99bill test !
2010-06-19 17:26:09  99bill test !
2010-06-19 17:26:14  99bill test !
2010-06-19 17:26:19  99bill test !

 

 

PS:

  代码修改过, 有朋友下载了我的代码,说如果是中文会乱码,将日志输出类的第30行的代码  
  System.out.println(tmp)改成 System.out.println(new String(tmp.getBytes("ISO8859-1"))),就会正常显示中文.