解决 log4j:ERROR Failed to rename,不需要修改源码

1.添加class文件

package com.test.util.logs;



import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InterruptedIOException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.Locale;
import java.util.TimeZone;


import org.apache.log4j.FileAppender;
import org.apache.log4j.Layout;
import org.apache.log4j.helpers.LogLog;
import org.apache.log4j.spi.LoggingEvent;


/**
 * 按日期生成日志文件 
 */
public class DailyRollingFileAppender extends FileAppender {


public static final int TOP_OF_TROUBLE = -1;
public static final int TOP_OF_MINUTE = 0;
public static final int TOP_OF_HOUR = 1;
public static final int HALF_DAY = 2;
public static final int TOP_OF_DAY = 3;
public static final int TOP_OF_WEEK = 4;
public static final int TOP_OF_MONTH = 5;


/**
* 日期模式。默认情况下,模式被设置为"yyyy-MM-dd"
*/
private String datePattern = "'.'yyyy-MM-dd";


/**
* 重命名日志文件名称
*/
private String scheduledFilename;

/**
* 日志文件最后一次修改时间
*/
private Date date;

/**
* 日志文件时是否生成完 true已生成完 false未生成完
*/
private  boolean status=true;


private long nextCheck = System.currentTimeMillis() - 1;
private Date now = new Date();
private SimpleDateFormat sdf;
private RollingCalendar rc = new RollingCalendar();
private static final TimeZone gmtTimeZone = TimeZone.getTimeZone("GMT");


public DailyRollingFileAppender() {
}


public DailyRollingFileAppender(Layout layout, String filename, String datePattern) throws IOException {
super(layout, filename, true);
this.datePattern = datePattern;
activateOptions();
}


public void setDatePattern(String pattern) {
datePattern = pattern;
}


public String getDatePattern() {
return datePattern;
}


/**
* 启动时获取日志文件最后一次修改时间
*/
public void activateOptions() {
super.activateOptions();
if (datePattern != null && fileName != null) {
now.setTime(System.currentTimeMillis());
sdf = new SimpleDateFormat(datePattern);
int type = computeCheckPeriod();
printPeriodicity(type);
rc.setType(type);
File file = new File(fileName);
date = new Date(file.lastModified());
scheduledFilename=fileName + sdf.format(date);
} else {
LogLog.error("Either File or DatePattern options are not set for appender [" + name + "].");
}
}


public void printPeriodicity(int type) {
switch (type) {
case TOP_OF_MINUTE:
LogLog.debug("Appender [" + name + "] to be rolled every minute.");
break;
case TOP_OF_HOUR:
LogLog.debug("Appender [" + name + "] to be rolled on top of every hour.");
break;
case HALF_DAY:
LogLog.debug("Appender [" + name + "] to be rolled at midday and midnight.");
break;
case TOP_OF_DAY:
LogLog.debug("Appender [" + name + "] to be rolled at midnight.");
break;
case TOP_OF_WEEK:
LogLog.debug("Appender [" + name + "] to be rolled at start of week.");
break;
case TOP_OF_MONTH:
LogLog.debug("Appender [" + name + "] to be rolled at start of every month.");
break;
default:
LogLog.warn("Unknown periodicity for appender [" + name + "].");
}
}


public int computeCheckPeriod() {
RollingCalendar rollingCalendar = new RollingCalendar(gmtTimeZone, Locale.getDefault());
Date epoch = new Date(0);
if (datePattern != null) {
for (int i = TOP_OF_MINUTE; i <= TOP_OF_MONTH; i++) {
SimpleDateFormat simpleDateFormat = new SimpleDateFormat(datePattern);
simpleDateFormat.setTimeZone(gmtTimeZone); // do all date formatting in GMT
String r0 = simpleDateFormat.format(epoch);
rollingCalendar.setType(i);
Date next = new Date(rollingCalendar.getNextCheckMillis(epoch));
String r1 = simpleDateFormat.format(next);
if (r0 != null && r1 != null && !r0.equals(r1)) {
return i;
}
}
}
return TOP_OF_TROUBLE;
}


/**
* 生成日志文件
*/
public void rollOver() throws IOException {
if (datePattern == null) {
errorHandler.error("Missing DatePattern option in rollOver().");
return;
}

//生成日志文件重命名名称
String datedFilename = fileName + sdf.format(now);

//当前时间生成的日志文件重命名名称与最后一次修改日志文件重命名名称相同,则表示不需要生成日志文件
if (scheduledFilename.equals(datedFilename)||!status) {
return;
}
//更改状态
status=false;

// 包含有不支持的字符串
String str = scheduledFilename.substring(fileName.length(), scheduledFilename.length());
if (str.contains("/") || str.contains("\\") || str.contains(":")
|| str.contains("*") || str.contains("\"")
|| str.contains("<") || str.contains(">") || str.contains("|")
|| str.contains("?")) {
String format = new SimpleDateFormat("yyyy年M月d日 H时m分s秒").format(date);
scheduledFilename = fileName + "(" + format + ").log";
}

this.closeFile();
// 文件存在就删除
File target = new File(scheduledFilename);
if (target.exists()) {
target.delete();
}

File file = new File(fileName);
boolean result = copy(file, target);
if (result) {
// 复制成功清空当前日志文件
FileWriter fw = new FileWriter(file);
fw.write("");
fw.flush();
fw.close();

LogLog.debug(fileName + " -> " + scheduledFilename);

//更改下次生成日志文件名称
date = new Date();
scheduledFilename = datedFilename;

} else {
LogLog.error("Failed to rename [" + fileName + "] to [" + scheduledFilename + "].");
}
try {
this.setFile(fileName, true, this.bufferedIO, this.bufferSize);
} catch (IOException e) {
errorHandler.error("setFile(" + fileName + ", true) call failed.");
}
//更改状态
status=true;
}


/**
* 复制文件
*/
public boolean copy(File src, File dst) throws IOException {
// 最大的流为60MB,当文件的容量大于60MB的时候便分开流
int MAX_BYTE = 60000000;
try {
long streamTotal = 0; // 接受流的容量
int streamNum = 0; // 流需要分开的数量
int leave = 0; // 文件剩下的字符数
byte[] inOutb;// byte数组接受文件的数据
FileInputStream in = new FileInputStream(src);
FileOutputStream out = new FileOutputStream(dst);
// 通过available方法取得流的最大字符数
streamTotal = in.available();
// 取得流文件需要分开的数量
streamNum = (int) Math.floor(streamTotal / MAX_BYTE);
// 分开文件之后,剩余的数量
leave = (int) (streamTotal % MAX_BYTE);
// 文件的容量大于60MB时进入循环
if (streamNum > 0) {
for (int i = 0; i < streamNum; i++) {
inOutb = new byte[MAX_BYTE];
// 读入流,保存在byte数组
in.read(inOutb, 0, MAX_BYTE);
out.write(inOutb);
out.flush();
}
}
// 剩余的流数据
inOutb = new byte[leave];
in.read(inOutb, 0, leave);
out.write(inOutb);
out.flush();
in.close();
out.close();
return true;
} catch (FileNotFoundException e) {
e.printStackTrace();
LogLog.error("源文件不存在,或者目标文件无法被识别.");
return false;
} catch (IOException e) {
LogLog.error("文件读写错误.");
return false;
}
}


protected void subAppend(LoggingEvent event) {
long n = System.currentTimeMillis();
if (n >= nextCheck) {
now.setTime(n);
nextCheck = rc.getNextCheckMillis(now);
try {
rollOver();
} catch (IOException ioe) {
if (ioe instanceof InterruptedIOException) {
Thread.currentThread().interrupt();
}
LogLog.error("rollOver() failed.", ioe);
}
}
super.subAppend(event);
}


}


/**
 * DailyRollingFileAppender的助手类 
 */
class RollingCalendar extends GregorianCalendar {

private static final long serialVersionUID = -3560331770601814177L;
int type = DailyRollingFileAppender.TOP_OF_TROUBLE;


RollingCalendar() {
super();
}


RollingCalendar(TimeZone tz, Locale locale) {
super(tz, locale);
}


void setType(int type) {
this.type = type;
}


public long getNextCheckMillis(Date now) {
return getNextCheckDate(now).getTime();
}


public Date getNextCheckDate(Date now) {
this.setTime(now);


switch (type) {
case DailyRollingFileAppender.TOP_OF_MINUTE:
this.set(Calendar.SECOND, 0);
this.set(Calendar.MILLISECOND, 0);
this.add(Calendar.MINUTE, 1);
break;
case DailyRollingFileAppender.TOP_OF_HOUR:
this.set(Calendar.MINUTE, 0);
this.set(Calendar.SECOND, 0);
this.set(Calendar.MILLISECOND, 0);
this.add(Calendar.HOUR_OF_DAY, 1);
break;
case DailyRollingFileAppender.HALF_DAY:
this.set(Calendar.MINUTE, 0);
this.set(Calendar.SECOND, 0);
this.set(Calendar.MILLISECOND, 0);
int hour = get(Calendar.HOUR_OF_DAY);
if (hour < 12) {
this.set(Calendar.HOUR_OF_DAY, 12);
} else {
this.set(Calendar.HOUR_OF_DAY, 0);
this.add(Calendar.DAY_OF_MONTH, 1);
}
break;
case DailyRollingFileAppender.TOP_OF_DAY:
this.set(Calendar.HOUR_OF_DAY, 0);
this.set(Calendar.MINUTE, 0);
this.set(Calendar.SECOND, 0);
this.set(Calendar.MILLISECOND, 0);
this.add(Calendar.DATE, 1);
break;
case DailyRollingFileAppender.TOP_OF_WEEK:
this.set(Calendar.DAY_OF_WEEK, getFirstDayOfWeek());
this.set(Calendar.HOUR_OF_DAY, 0);
this.set(Calendar.MINUTE, 0);
this.set(Calendar.SECOND, 0);
this.set(Calendar.MILLISECOND, 0);
this.add(Calendar.WEEK_OF_YEAR, 1);
break;
case DailyRollingFileAppender.TOP_OF_MONTH:
this.set(Calendar.DATE, 1);
this.set(Calendar.HOUR_OF_DAY, 0);
this.set(Calendar.MINUTE, 0);
this.set(Calendar.SECOND, 0);
this.set(Calendar.MILLISECOND, 0);
this.add(Calendar.MONTH, 1);
break;
default:
throw new IllegalStateException("Unknown periodicity type.");
}
return getTime();
}

}

2.配置log4j.properties使用该class

log4j.rootLogger=ERROR,Console,File


#定义日志输出目的地为控制台 
log4j.appender.Console=org.apache.log4j.ConsoleAppender
log4j.appender.Console.Target=System.out


#指定日志输出格式
log4j.appender.Console.layout=org.apache.log4j.PatternLayout
log4j.appender.Console.layout.ConversionPattern=[%c] %m%n


#每天产生一个新文件
log4j.appender.File=上面class文件路径


#指定输出目录  
log4j.appender.File.File=../logs/log4j/test


#定义文件日期  通过时间格式来确认日志文件生成间隔
log4j.appender.File.DatePattern='('yyyy-MM-dd').log'


# 输出所以日志,如果换成DEBUG表示输出DEBUG以上级别日志 
log4j.appender.File.Threshold=ALL
log4j.appender.File.layout=org.apache.log4j.PatternLayout
log4j.appender.File.layout.ConversionPattern=[%d{yyyy-MM-dd HH\:mm\:ss(SSS)}][%p][%c] - %m%n


#显示本项目SQL语句部分
log4j.logger.com.test=DEBUG




评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值