在使用JAVA的日志记录功能时,我们通过java.util.logging.Logger对象来记录特定系统或应用程序组件的日志消息 。在记录日志时它使用java.util.logging.Handler来处理日志的记录,例如:如果使用的是FileHandler,那么处理器控制日志文件的位置、大小以及是否将新的日志内容添加到原有的日志文件中等。 java.util.logging.Formatter对象用于控制日志内容的输出格式,java.util.logging.LogRecord 对象用于在日志框架和单个日志 Handler 之间传递日志请求,它封装了日志的基本内容。在记录日志时Handler通过将LogRecord对象传递给Formatter,获得格式化好的日志信息后将其写入输出流中。
虽然JAVA日志包提供的功能已经很方便,但是假如我们有新的需求如:将日志文件保存到我们希望的位置并在日志文件名中添加日期且保存指定时间内的日志文件;按照自己希望的格式输出日志内容。对于这些需求我们只要扩展java.util.logging.StreamHandler(Handler的子类),java.util.logging.Formatter创建自定义的处理器及格式化器即可以实现。下面是个例子,它分别创建了Handler及Formatter的子类,以便实现将日志文件保存到我们需要的位置,及在日志文件名中保存日志的生成日期,允许你设置需要保存几天内的日志文件,允许设置每个日志文件的大小。
(1)com.ckcs.log.customlog.CustomFileStreamHandler自定义文件处理器
虽然JAVA日志包提供的功能已经很方便,但是假如我们有新的需求如:将日志文件保存到我们希望的位置并在日志文件名中添加日期且保存指定时间内的日志文件;按照自己希望的格式输出日志内容。对于这些需求我们只要扩展java.util.logging.StreamHandler(Handler的子类),java.util.logging.Formatter创建自定义的处理器及格式化器即可以实现。下面是个例子,它分别创建了Handler及Formatter的子类,以便实现将日志文件保存到我们需要的位置,及在日志文件名中保存日志的生成日期,允许你设置需要保存几天内的日志文件,允许设置每个日志文件的大小。
(1)com.ckcs.log.customlog.CustomFileStreamHandler自定义文件处理器
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package com.ckcs.log.customlog;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.OutputStream;
import java.text.ParsePosition;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.LinkedList;
import java.util.logging.Level;
import java.util.logging.LogRecord;
import java.util.logging.Logger;
import java.util.logging.StreamHandler;
/**
* 自定义日志文件处理器
* @author Administrator
*/
public class CustomFileStreamHandler extends StreamHandler {
//输出流
private MeteredStream msOut;
//日志玩家的写入的字节数, limit 为0 表示没有限制
private int limit = 50000;
//是否添加的玩家末尾
private boolean append;
//保存存在的日志文件
private LinkedList<File> files;
//希望写入的日志路径
private String fileUrl;
//保存几天之内的日志文件
private int dateInter = 1;
//索引文件,用于记录当前日志记录信息,请不要认为的修改
private File indexFile;
/**
* 初始化自定义文件流处理器
* @param fileUrl 文件路径, 可以是个目录或希望的日志名称,如果是个目录则日志为“未命名”
* 指定日志名称时不需要包括日期,程序会自动生成日志文件的生成日期及相应的编号
* @param limit 每个日志希望写入的最大字节数,如果日志达到最大字节数则当天日期的一个新的编 号的日志文件将被创建,最新的日志记录在最大编号的文件中
* @param dateInter 事务保存的日期间隔
* @param append 是否将日志写入已存在的日志文件中
* @throws java.lang.Exception
*/
public CustomFileStreamHandler(String fileUrl, int limit, int dateInter, boolean append) throws Exception {
super();
this.fileUrl = fileUrl;
if (dateInter <= 0) {
throw new IllegalArgumentException("时间间隔必须大于0");
}
if (limit <= 0) {
throw new IllegalArgumentException("写入日志文件的最大字节数必须大于0");
}
this.limit = limit;
this.dateInter = dateInter;
this.append = append;
openWriteFiles();
}
public CustomFileStreamHandler(String fileUrl, boolean append) throws Exception {
super();
this.fileUrl = fileUrl;
this.append = append;
openWriteFiles();
}
/**
* 获得将要写入的文件
*/
private synchronized void openWriteFiles() throws Exception {
if (fileUrl == null) {
throw new IllegalArgumentException("文件路径不能为null");
}
files = getWritedLog();
checkLogFile();
if (append) {
openFile(files.getLast(), append);
} else {
getLastFile();
}
}
/**
* 打开需要写入的文件
* @param file 需要打开的文件
* @param append 是否将内容添加到文件末尾
*/
private void openFile(File file, boolean append) throws Exception {
//System.out.println("***opend = true " + file.toString());
int len = 0;
if (append) {
len = (int) file.length();
}
FileOutputStream fout = new FileOutputStream(file.toString(), append);
BufferedOutputStream bout = new BufferedOutputStream(fout);
msOut
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package com.ckcs.log.customlog;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.OutputStream;
import java.text.ParsePosition;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.LinkedList;
import java.util.logging.Level;
import java.util.logging.LogRecord;
import java.util.logging.Logger;
import java.util.logging.StreamHandler;
/**
* 自定义日志文件处理器
* @author Administrator
*/
public class CustomFileStreamHandler extends StreamHandler {
//输出流
private MeteredStream msOut;
//日志玩家的写入的字节数, limit 为0 表示没有限制
private int limit = 50000;
//是否添加的玩家末尾
private boolean append;
//保存存在的日志文件
private LinkedList<File> files;
//希望写入的日志路径
private String fileUrl;
//保存几天之内的日志文件
private int dateInter = 1;
//索引文件,用于记录当前日志记录信息,请不要认为的修改
private File indexFile;
/**
* 初始化自定义文件流处理器
* @param fileUrl 文件路径, 可以是个目录或希望的日志名称,如果是个目录则日志为“未命名”
* 指定日志名称时不需要包括日期,程序会自动生成日志文件的生成日期及相应的编号
* @param limit 每个日志希望写入的最大字节数,如果日志达到最大字节数则当天日期的一个新的编 号的日志文件将被创建,最新的日志记录在最大编号的文件中
* @param dateInter 事务保存的日期间隔
* @param append 是否将日志写入已存在的日志文件中
* @throws java.lang.Exception
*/
public CustomFileStreamHandler(String fileUrl, int limit, int dateInter, boolean append) throws Exception {
super();
this.fileUrl = fileUrl;
if (dateInter <= 0) {
throw new IllegalArgumentException("时间间隔必须大于0");
}
if (limit <= 0) {
throw new IllegalArgumentException("写入日志文件的最大字节数必须大于0");
}
this.limit = limit;
this.dateInter = dateInter;
this.append = append;
openWriteFiles();
}
public CustomFileStreamHandler(String fileUrl, boolean append) throws Exception {
super();
this.fileUrl = fileUrl;
this.append = append;
openWriteFiles();
}
/**
* 获得将要写入的文件
*/
private synchronized void openWriteFiles() throws Exception {
if (fileUrl == null) {
throw new IllegalArgumentException("文件路径不能为null");
}
files = getWritedLog();
checkLogFile();
if (append) {
openFile(files.getLast(), append);
} else {
getLastFile();
}
}
/**
* 打开需要写入的文件
* @param file 需要打开的文件
* @param append 是否将内容添加到文件末尾
*/
private void openFile(File file, boolean append) throws Exception {
//System.out.println("***opend = true " + file.toString());
int len = 0;
if (append) {
len = (int) file.length();
}
FileOutputStream fout = new FileOutputStream(file.toString(), append);
BufferedOutputStream bout = new BufferedOutputStream(fout);
msOut