/*
* Created on 2005-7-29 - 22:45:27 by jerry.li
* Filename is SimpleLog.java
*
* Any question,mailto fdabobi@gmail.com
*
* Use eclipse and default encoding ‘GBK‘
*/
package cn.zhuazi.util;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
/**
* 该类是一个简单的日志记录器,按日期生成日志文件
* @author Administrator
*
*/
public class SimpleLog {
/** 默认文件名 */
protected static final String DEFAULT_NAME = "MyLog";
/** 默认存储方式 */
protected static final boolean DEFAULT_METHOD = false;
/** 默认缓存大小 */
protected static final int DEFAULT_SIZE = 10;
/** 日志间的分隔符 */
protected static final String SEP = "\n";
/** 缓存大小 */
protected int messageSize = 0;
/** 文件前缀 */
protected String fileName = null;
/** 当前文件名,不含.log */
protected String currentLogFile = "";
/** 当前是否使用缓存 */
protected boolean bufferMethod = DEFAULT_METHOD;
/** 以 List 实现的缓存 */
protected List bufferedMessage;
/**
* 默认构造函数,使用默认值构造日志记录器
*/
public SimpleLog(){
init(DEFAULT_NAME,DEFAULT_SIZE,DEFAULT_METHOD);
}
/**
* 指定文件前缀与缓存大小,缓存将自动启用
* @param fileName 文件前缀,不含日期
* @param bufferSize 缓存大小 10~200,超过200以200计,低与10以10计
*/
public SimpleLog(String fileName,int bufferSize){
bufferSize = (bufferSize >= 10 && bufferSize <= 200) ?
bufferSize : ((bufferSize > 200) ? 200 : 10);
init(fileName,bufferSize,true);
}
/**
* 指定文件前缀与是否启用缓存,缓存将使用默认值: {@link #DEFAULT_METHOD}
* @param fileName
* @param bufferMethod
*/
public SimpleLog(String fileName,boolean bufferMethod){
init(fileName,DEFAULT_SIZE,true);
}
/**
* 根据指定参数初始化实例,并计算当前文件名
* @param fileName 文件前缀
* @param bufferSize 缓存大小
* @param bufferMethod 是否启用缓存
*/
protected void init(String fileName,int bufferSize,boolean bufferMethod){
this.messageSize = bufferSize;
this.fileName = fileName;
this.bufferMethod = bufferMethod;
if (bufferMethod){
this.bufferedMessage = Collections.synchronizedList(new ArrayList());
}
//先计算文件名
this.currentLogFile = this.fileName + this.getDateString();
}
/**
* 处理日志信息,判断{@link #bufferMethod}
,
* true : 将日志缓存,直到缓存超出{@link #messageSize}
,则追加到文件尾部
* false : 将日志直接追加到文件尾部
* 注意 : 缓存模式中,请在应用程序退出前调用{@link #forceClearBufferAtOnce()}
提交
,
* 否则缓存中未及时保存的信息将丢失
* @param message 要保存的信息
* @return true保存成功 false保存失败
*/
public synchronized boolean processLog(String message){
String tempName = this.fileName + getDateString();
// 生成文件名并判断是否日期已经更换
if (!currentLogFile.equals(tempName)){
if (bufferMethod)
{
// 日期更换则先强行提交
try {
forceClearBufferAtOnce();
} catch (Exception e) {
// 忽略错误
}
}
// 文件名替换
currentLogFile = tempName;
}
// 根据记录模式选择对应的记录方式
try {
if (bufferMethod){
processLogWithBuffer(message,false);
}else{
processLogAtOnce(message);
}
} catch (IOException e) {
// 保存过程捕捉到错误
return false;
}
// 准确完成
return true;
}
/**
* 将消息立即保存到以{@link #currentLogFile}
命名的.log文件,
* 使用 java.io.RandomAccessFile 进行保存,并且以插入分隔符 {@link #SEP}
* @param message
* @throws IOException 保存失败时抛出
*/
protected void processLogAtOnce(String message) throws IOException{
File currentFile = new File(currentLogFile + ".log");
if (!currentFile.exists()){
currentFile.createNewFile();
}
//FileWriter out = new FileWriter(currentFile);
RandomAccessFile out = new RandomAccessFile(currentFile,"rw");
out.seek(out.length());
out.writeBytes(SEP);
out.write(message.getBytes());
out.close();
}
/**
* 将消息保存到 {@link #bufferedMessage}
,直到缓存达到指定数,
* 使用 {@link #processLogAtOnce(String)}
立即保存消息
* @param message
* @param force 忽略缓存大小,强制保存
* @throws IOException 保存失败时抛出
*/
protected synchronized void processLogWithBuffer(String message,boolean force) throws IOException{
// 先保存消息
if (message != null){
bufferedMessage.add(message);
}
// 判断是否需要立即保存到文件
if (force || bufferedMessage.size() >= messageSize){
StringBuffer sb = new StringBuffer();
Iterator it = bufferedMessage.iterator();
if (it.hasNext()){
do {
sb.append(SEP + it.next());
} while (it.hasNext());
}
/*if (force){
System.out.println("Save at once cause force!");
}else{
System.out.println("Save at once cause buffer full!");
}*/
//截取字符串首个分隔符,因为系统自动会在消息前加
processLogAtOnce(sb.substring(SEP.length()));
bufferedMessage.clear();
}
}
/**
* 强制将缓存中的消息保存到文件
* @return true保存成功 false保存失败
* @throws Exception 非缓存模式
*/
public boolean forceClearBufferAtOnce() throws Exception{
if (!bufferMethod){
throw new Exception("Not buffer model, can‘t force clear!");
}
try {
processLogWithBuffer(null,true);
} catch (IOException e) {
return false;
}
return true;
}
/**
* TODO 以更好的算法替换每次记录都判断时间
*
* 获取日期字符串,不包含时间
* @return 表示日期的字符串
*/
protected String getDateString(){
String date = new Date().toLocaleString();
return date.substring(0,date.indexOf(" "));
}
public static void main(String[] args) throws Exception{
System.out.println("not buffer model start!");
SimpleLog log = new SimpleLog();
Date d1 = new Date();
for (int i = 0; i < 30 ; ++ i){
log.processLog("哈哈,This is my log, number : " + i);
}
Date d2 = new Date();
System.out.println("not buffer model over! Time : " + (d2.getTime() - d1.getTime()));
System.out.println("buffer model start!");
log = new SimpleLog("YourLog",25);
Date d3 = new Date();
for (int i = 0; i < 30 ; ++ i){
log.processLog("哈哈,This is my log, number : " + i);
}
log.forceClearBufferAtOnce();
Date d4 = new Date();
System.out.println("buffer model over! Time : " + (d4.getTime() - d3.getTime()));
String date = d4.toLocaleString();
File f1 = new File("MyLog" + date.substring(0,date.indexOf(" ")) + ".log");
File f2 = new File("YourLog" + date.substring(0,date.indexOf(" ")) + ".log");
FileReader read1 = new FileReader(f1);
FileReader read2 = new FileReader(f2);
BufferedReader br1 = new BufferedReader(read1);
BufferedReader br2 = new BufferedReader(read2);
String str = null;
while ((str = br1.readLine()) != null){
System.out.println((str));
}
while ((str = br2.readLine()) != null){
System.out.println((str));
}
}
}