Posted on 2009-05-30 23:42
啥都寫點 閱讀(487)
評論(0) 編輯 收藏 所屬分類:
J2SE
關鍵技術:
- 使用Singleton單例模式,使得整個程序中只存在一個日志類的實例。
- 寫日志文件使用java.io.PrintWriter,是因為它能對文本進行格式化的寫入。
- 通過配置文件的方式,允許用戶修改日志文件的路徑。使用java.util.Properties類解析配置文件。
- 為了避免多線程同時寫文件造成的日志紊亂,在寫日志消息時,使用同步機制。
package book.io.log;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.util.Properties;
import book.io.ReadFromFile;
/**
* 日志工具類
* 使用了單例模式,保證只有一個實例。
* 為了更方便的配置日志文件名,使用屬性文件配置。
* 也可以在程序中指定日志文件名。
*/
public class LogWriter {
// 日志的配置文件
public static final String LOG_CONFIGFILE_NAME = "log.properties";
// 日志文件名在配置文件中的標簽
public static final String LOGFILE_TAG_NAME = "logfile";
// 默認的日志文件的路徑和文件名稱
private final String DEFAULT_LOG_FILE_NAME = "./logtext.log";
// 該類的唯一的實例
private static LogWriter logWriter;
// 文件輸出流
private PrintWriter writer;
// 日志文件名
private String logFileName;
/**
* 默認構造函數
*/
private LogWriter() throws LogException{
this.init();
}
private LogWriter(String fileName) throws LogException{
this.logFileName = fileName;
this.init();
}
/**
* 獲取LogWriter的唯一實例。
* @return
* @throws LogException
*/
public synchronized static LogWriter getLogWriter()throws LogException{
if (logWriter == null){
logWriter = new LogWriter();
}
return logWriter;
}
public synchronized static LogWriter getLogWriter(String logFileName)throws LogException{
if (logWriter == null){
logWriter = new LogWriter(logFileName);
}
return logWriter;
}
/**
* 往日志文件中寫一條日志信息
* 為了防止多線程同時操作(寫)日志文件,造成文件”死鎖”。使用synchronized關鍵字
* @param logMsg 日志消息
*/
public synchronized void log(String logMsg) {
this.writer.println(new java.util.Date() + ": " + logMsg);
}
/**
* 往日志文件中寫一條異常信息
* 使用synchronized關鍵字。
* @param ex 待寫入的異常
*/
public synchronized void log(Exception ex) {
writer.println(new java.util.Date() + ": ");
ex.printStackTrace(writer);
}
/**
* 初始化LogWriter
* @throws LogException
*/
private void init() throws LogException{
//如果用戶沒有在參數中指定日志文件名,則從配置文件中獲取。
if (this.logFileName == null){
this.logFileName = this.getLogFileNameFromConfigFile();
//如果配置文件不存在或者也沒有指定日志文件名,則用默認的日志文件名。
if (this.logFileName == null){
this.logFileName = DEFAULT_LOG_FILE_NAME;
}
}
File logFile = new File(this.logFileName);
try {
// 其中的FileWriter()中的第二個參數的含義是:是否在文件中追加內容
// PrintWriter()中的第二個參數的含義是:自動將數據flush到文件中
writer = new PrintWriter(new FileWriter(logFile, true), true);
System.out.println("日志文件的位置:" + logFile.getAbsolutePath());
} catch (IOException ex) {
String errmsg = "無法打開日志文件:" + logFile.getAbsolutePath();
// System.out.println(errmsg);
throw new LogException(errmsg, ex);
}
}
/**
* 從配置文件中取日志文件名
* @return
*/
private String getLogFileNameFromConfigFile() {
try {
Properties pro = new Properties();
//在類的當前位置,查找屬性配置文件log.properties
InputStream fin = getClass().getResourceAsStream(LOG_CONFIGFILE_NAME);
if (fin != null){
pro.load(fin);//載入配置文件
fin.close();
return pro.getProperty(LOGFILE_TAG_NAME);
} else {
System.err.println("無法打開屬性配置文件: log.properties" );
}
}catch (IOException ex) {
System.err.println("無法打開屬性配置文件: log.properties" );
}
return null;
}
//關閉LogWriter
public void close() {
logWriter = null;
if (writer != null){
writer.close();
}
}
public static void main(String[] args) {
LogWriter logger = null;
try {
String fileName = "C:/temp/temp0/logger.log";
logger = LogWriter.getLogWriter(fileName);
logger.log("First log!");
logger.log("第二個日志信息");
logger.log("Third log");
logger.log("第四個日志信息");
logger.close();
ReadFromFile.readFileByLines(fileName);
} catch (LogException e) {
e.printStackTrace();
}
}
}
/**
*Log操作過程中的異常
*/
package book.io.log;
/**
* Log操作過程中的異常
*/
public class LogException extends Exception {
public LogException() {
super();
}
public LogException(String msg) {
super(msg);
}
public LogException(String msg, Throwable cause) {
super(msg, cause);
}
public LogException(Throwable cause) {
super(cause);
}
}
--
學海無涯