- 浏览: 344426 次
- 性别:
- 来自: 北京
文章分类
- 全部博客 (249)
- 无废话ExtJs 系列教程 (26)
- jQuery (6)
- 钦波工作后的生活 (5)
- 工作/生活闲谈 (16)
- java基础知识 (44)
- java web (14)
- Struts (1)
- hibernate (8)
- Jpa (0)
- spring (1)
- ajax (3)
- java项目 (4)
- database (5)
- java 流行框架 (5)
- 异常处理 (4)
- 无废话Android系统教程 (6)
- 开发IDE (1)
- 亲自答过的java笔试题 (2)
- oa项目 (4)
- [ 民政局3.0系统 ]--知识点总结分析--与具体项目无关 (0)
- [ 黑龙江低保系统 ]--知识点总结分析--与具体项目无关 (2)
- 工作笔试 (1)
- xml (1)
- telecom项目分析 (13)
- swing (0)
- String运用 (2)
- css (1)
- 页面 (1)
- Html5 (2)
- oracle (4)
- 网站 (1)
- django (1)
- python (4)
- 民航数据中心遇到与解决的问题 (1)
- 平时关注的技术或特效 (1)
- Linux 命令 (2)
- 服务器监控工具 (1)
最新评论
-
wwytwen123:
[*]
java类中静态域、块,非静态域、块,构造函数的初始化顺序(回钦波) -
junying280efun:
yingtao.huang@gmail.com仁兄,麻烦你给我 ...
jBPM Web Designer(jBPM Web 设计器、jBPM 流程设计器、工作流程设计器) -
mobeicanglang:
我觉得楼主的例子全部都有错误,题目明明说的是try{}语句中有 ...
try return finally -
ashy1q:
楼主最后那段代码重复了,写了两遍。知识很详细,很基础,学习了。 ...
java类中静态域、块,非静态域、块,构造函数的初始化顺序(回钦波) -
185552143:
你好!
为什么我这样写p${m.id},会报错的?
能我帮我解 ...
Session问题
为java.util.logging自定义文件处理器及日志输出格式
最近闲来无事,刚好拾起了来公司的第一个项目,发现里面的logging功能有点弱,竟然不支持按日期文件名输出,更惨的是由于引入了些apache的公用了包,一个项目里竟然同时出现logging,log4j,commons-logging,这年头引用下开源包还要用不同的loger.记得log4j好像支持输出的文件按日期来分类的,jdk自带的logging好像还没有,于是google了一把,发现JAVA中自定义日志输出格式及自定义文件处理器的实现 ,功能还不错,有些bug及不合理的地方,于是再修改下,凑合用用.
直接代码:
FileStreamHandler实现
- package com.huiqinbo;
- import java.io.BufferedOutputStream;
- import java.io.File;
- import java.io.FileOutputStream;
- import java.io.IOException;
- import java.io.OutputStream;
- import java.text.SimpleDateFormat;
- import java.util.Date;
- import java.util.HashMap;
- import java.util.Map;
- import java.util.TreeSet;
- import java.util.logging.Filter;
- import java.util.logging.Formatter;
- import java.util.logging.Handler;
- import java.util.logging.Level;
- import java.util.logging.LogManager;
- import java.util.logging.LogRecord;
- import java.util.logging.Logger;
- import java.util.logging.StreamHandler;
- /**
- * 自定义日志文件处理器---日期及文件大小存储,并自动清除过期日志文件
- *
- * @author huiqinbo
- * @time 2008-9-11下午11:16:39
- */
- public class XLFileStreamHandler extends StreamHandler {
- /**
- * 抄自FileHandler的实现,用于跟踪写入文件的字节数 这样以便提高效率
- */
- private class MeteredStream extends OutputStream {
- private OutputStream out;
- // 记录当前写入字节数
- private int written;
- MeteredStream(OutputStream out, int written) {
- this.out = out;
- this.written = written;
- }
- public void close() throws IOException {
- out.close();
- }
- public void flush() throws IOException {
- out.flush();
- }
- public void write(byte buff[]) throws IOException {
- out.write(buff);
- written += buff.length;
- }
- public void write(byte buff[], int off, int len) throws IOException {
- out.write(buff, off, len);
- written += len;
- }
- public void write(int b) throws IOException {
- out.write(b);
- written++;
- }
- }
- private class XLLogFile extends File {
- private static final long serialVersionUID = 952141123094287978L;
- private Date date;
- private String dateString;
- private int sid;
- public int getSid() {
- return this.sid;
- }
- public void setSid(int sid) {
- this.sid = sid;
- }
- public Date getDate() {
- return this.date;
- }
- public void setDate(Date date) {
- this.date = date;
- }
- public String getDateString() {
- return this.dateString;
- }
- public void setDateString(String dateString) {
- this.dateString = dateString;
- }
- public int compareTo(File another) {
- XLLogFile ano = (XLLogFile) another;
- int dateComResult = date.compareTo(ano.getDate());
- if (dateComResult == 0) {
- return sid - ano.getSid();
- }
- return dateComResult;
- }
- SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
- public XLLogFile(String pathname) {
- super(pathname);
- try {
- int dot = pathname.lastIndexOf('.');
- int split = pathname.lastIndexOf(splitDateIndexChar);
- int underline = pathname.lastIndexOf('_');
- dateString = pathname.substring(underline + 1, split);
- String numStr = pathname.substring(split + 1, dot);
- date = sdf.parse(dateString);
- sid = Integer.valueOf(numStr);
- } catch (Exception e) {
- System.err.println("log对应文件夹中包含了不符合XLLOG格式的文件!!");
- e.printStackTrace();
- }
- }
- }
- private static final String undifine = "xlcallcenter";
- // 是否将日志写入已存在的日志文件中
- private boolean append;
- // 保存几天之内的日志文件
- // 时间间隔小于等于0时表明不删除历史记录
- private int dateinterval = 5;
- // 保存存在的日志文件
- private Map<String, TreeSet<XLLogFile>> files;
- // 每个日志希望写入的最大字节数,如果日志达到最大字节数则当天日期的一个新的编号的日志文件将被创建,最新的日志记录在最大编号的文件中
- // 文件大小为小于等于0时表明不限制日志文件大小
- private int limit = 1048576 * 5;
- // 输出流
- private MeteredStream msOut;
- // 文件路径, 可以是个目录或希望的日志名称,如果是个目录则日志为"callcenter_zd"
- // 指定日志名称时不需要包括日期,程序会自动生成日志文件的生成日期及相应的编号
- private String pattern = "./log/xunleidemo";
- private char splitDateIndexChar = '#';
- public XLFileStreamHandler() throws Exception {
- configure();
- openWriteFiles();
- }
- /**
- * 初始化自定义文件流处理器
- *
- * @param fileUrl
- * 文件路径, 可以是个目录或希望的日志名称,如果是个目录则日志为"callcenter_zd"
- * 指定日志名称时不需要包括日期,程序会自动生成日志文件的生成日期及相应的编号
- * @param limit
- * 每个日志希望写入的最大字节数,如果日志达到最大字节数则当天日期的一个新的编
- * 号的日志文件将被创建,最新的日志记录在最大编号的文件中
- * @param dateinterval
- * 保存几天之内的日志文件
- * @param append
- * 是否将日志写入已存在的日志文件中
- * @throws java.lang.Exception
- */
- public XLFileStreamHandler(String fileUrl, int limit, int dateinterval,
- boolean append) throws Exception {
- super();
- this.pattern = fileUrl;
- this.limit = limit;
- this.dateinterval = dateinterval;
- this.append = append;
- openWriteFiles();
- }
- /**
- * 检查当前日志时间,删除过期日志
- */
- private void deleteExpiredLog() {
- try {
- // 今天作为基准
- SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
- String today = sdf.format(new Date().getTime());
- // 删除过期日志
- for (String keyDate : files.keySet()) {
- if ((sdf.parse(today).getTime() - sdf.parse(keyDate).getTime())
- / (86400 * 1000) > dateinterval) {
- TreeSet<XLLogFile> traceDateFiles = files.get(keyDate);
- for (File deletingFile : traceDateFiles) {
- // if(deletingFile.exists()) {
- deletingFile.delete();
- // }
- }
- files.remove(today);
- }
- }
- } catch (Exception ex) {
- Logger.getLogger(XLFileStreamHandler.class.getName()).log(
- Level.SEVERE, null, ex);
- }
- }
- // Private method to configure a FileHandler from LogManager
- // properties and/or default values as specified in the class
- // javadoc.
- private void configure() {
- LogManager manager = LogManager.getLogManager();
- String cname = getClass().getName();
- // 获得pattern
- pattern = manager.getProperty(cname + ".pattern");
- if (pattern == null) {
- pattern = "./log/xunleidemo";
- }
- // 获得limit
- String limitVal = manager.getProperty(cname + ".limit");
- if (limitVal == null) {
- limit = 1048576 * 5;
- } else {
- try {
- limit = Integer.parseInt(limitVal.trim());
- // if (limit < 0) {
- // limit = 1048576 * 5;
- // }
- } catch (Exception ex) {
- limit = 1048576 * 5;
- }
- }
- // 获得formatter
- String formatVal = manager.getProperty(cname + ".formatter");
- if (formatVal == null) {
- setFormatter(new XLLogFormatter());
- } else {
- try {
- Class clz = ClassLoader.getSystemClassLoader().loadClass(
- formatVal);
- setFormatter((Formatter) clz.newInstance());
- } catch (Exception ex) {
- // We got one of a variety of exceptions in creating the
- // class or creating an instance.
- // Drop through.
- }
- }
- // 获得append
- String appendVal = manager.getProperty(cname + ".append");
- if (appendVal == null) {
- append = false;
- } else {
- if (appendVal.equalsIgnoreCase("true") || appendVal.equals("1")) {
- append = true;
- } else if (appendVal.equalsIgnoreCase("false")
- || appendVal.equals("0")) {
- append = false;
- }
- }
- // 获得level
- String levelVal = manager.getProperty(cname + ".level");
- if (levelVal == null) {
- setLevel(Level.ALL);
- } else {
- try {
- setLevel(Level.parse(levelVal.trim()));
- } catch (Exception ex) {
- setLevel(Level.ALL);
- }
- }
- // 获得dateinterval
- String dateintervalVal = manager.getProperty(cname + ".dateinterval");
- if (dateintervalVal == null) {
- dateinterval = 5;
- } else {
- try {
- dateinterval = Integer.parseInt(dateintervalVal.trim());
- if (dateinterval <= 0) {
- dateinterval = 5;
- }
- } catch (Exception ex) {
- dateinterval = 5;
- }
- }
- // 获得filter
- String filterVal = manager.getProperty(cname + ".filter");
- if (filterVal == null) {
- setFilter(null);
- } else {
- try {
- Class clz = ClassLoader.getSystemClassLoader().loadClass(
- filterVal);
- setFilter((Filter) clz.newInstance());
- } catch (Exception ex) {
- // We got one of a variety of exceptions in creating the
- // class or creating an instance.
- // Drop through.
- }
- }
- // 获得encoding
- String encodingVal = manager.getProperty(cname + ".encoding");
- if (encodingVal == null) {
- try {
- setEncoding(null);
- } catch (Exception ex2) {
- // doing a setEncoding with null should always work.
- // assert false;
- }
- } else {
- try {
- setEncoding(encodingVal);
- } catch (Exception ex) {
- try {
- setEncoding(null);
- } catch (Exception ex2) {
- // doing a setEncoding with null should always work.
- // assert false;
- }
- }
- }
- }
- /**
- * 将离现在最近的文件作为写入文件的文件 例如 xunleidemo_2008-02-19#30.log
- * xunleidemo表示自定义的日志文件名,2008-02-19表示日志文件的生成日期,30 表示此日期的第30个日志文件
- */
- private void openLastFile(boolean append) {
- try {
- super.close();
- SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
- String today = sdf.format(new Date().getTime());
- // 如果没有包含当天的日期,则添加当天日期的日志文件
- boolean isFirstLogToday = false;
- if (!files.containsKey(today)) {
- String logIndex = today + splitDateIndexChar + 1;
- TreeSet<XLLogFile> todayFiles = new TreeSet<XLLogFile>();
- todayFiles.add(getNewFile(logIndex));
- files.put(today, todayFiles);
- isFirstLogToday = true;
- }
- // 获得今天最大的日志文件编号
- XLLogFile todayLastFile = files.get(today).last();
- int maxLogCount = todayLastFile.getSid();
- String logIndex = today + splitDateIndexChar
- + (maxLogCount + (isFirstLogToday ? 0 : (append ? 0 : 1)));
- XLLogFile wantWriteFile = getNewFile(logIndex);
- files.get(today).add(wantWriteFile);
- openFile(wantWriteFile, append);
- } catch (Exception ex) {
- Logger.getLogger(XLFileStreamHandler.class.getName()).log(
- Level.SEVERE, null, ex);
- }
- }
- /**
- * 根据logIndex要建立File
- *
- * @param logIndex
- * 包含今天日期及编号,如2008-09-11#1
- * @return File
- */
- private XLLogFile getNewFile(String logIndex) {
- File file = new File(pattern);
- XLLogFile wantWriteFile = null;
- StringBuilder filePath = new StringBuilder(pattern);
- if (file.isDirectory()) {
- filePath.append(File.separator);
- filePath.append(undifine);
- }
- filePath.append('_');
- filePath.append(logIndex);
- filePath.append(".log");
- wantWriteFile = new XLLogFile(filePath.toString());
- return wantWriteFile;
- }
- /**
- * 读取已经记录的日志的时间信息
- */
- private Map<String, TreeSet<XLLogFile>> getRecodedLog() {
- Map<String, TreeSet<XLLogFile>> filesMap = new HashMap<String, TreeSet<XLLogFile>>();
- try {
- // 建立相关目录
- File file = new File(pattern);
- File fileDir = null;
- if (pattern.endsWith("/") || pattern.endsWith("\\")) {
- // 是个目录
- fileDir = file;
- if (!file.exists()) {
- file.mkdirs();
- }
- } else {
- // 带了前缀
- File parentFile = new File(file.getParent());
- fileDir = parentFile;
- // 父目录不存在则新建目录
- if (!parentFile.exists()) {
- parentFile.mkdirs();
- }
- }
- // 加入到filesMap中
- for (File contentFile : fileDir.listFiles()) {
- if (contentFile.isFile()) {
- XLLogFile newXLLogFile = new XLLogFile(contentFile
- .getAbsolutePath());
- TreeSet<XLLogFile> fileListToDate = filesMap
- .get(newXLLogFile.getDateString());
- if (fileListToDate == null) {
- fileListToDate = new TreeSet<XLLogFile>();
- }
- fileListToDate.add(newXLLogFile);
- filesMap.put(newXLLogFile.getDateString(), fileListToDate);
- }
- }
- files = filesMap;
- return filesMap;
- } catch (Exception ex) {
- Logger.getLogger(XLFileStreamHandler.class.getName()).log(
- Level.SEVERE, null, ex);
- }
- return null;
- }
- /**
- * 打开需要写入的文件
- *
- * @param file
- * 需要打开的文件
- * @param append
- * 是否将内容添加到文件末尾
- */
- private void openFile(File file, boolean append) throws Exception {
- int len = 0;
- if (append) {
- len = (int) file.length();
- }
- FileOutputStream fout = new FileOutputStream(file.toString(), append);
- BufferedOutputStream bout = new BufferedOutputStream(fout);
- msOut = new MeteredStream(bout, len);
- setOutputStream(msOut);
- }
- /**
- * 获得将要写入的文件
- */
- private synchronized void openWriteFiles() throws Exception {
- if (!getLevel().equals(Level.OFF)) {
- getRecodedLog();
- deleteExpiredLog();
- openLastFile(append);
- }
- }
- /**
- * 发布日志信息
- */
- public synchronized void publish(LogRecord record) {
- super.publish(record);
- super.flush();
- if (getLevel().equals(Level.OFF)) {
- return;
- }
- if (limit > 0 && msOut.written >= limit) {
- openLastFile(false);
- }
- }
- public static void main(String[] args) {
- Logger fileLogger = Logger.getLogger(XLFileStreamHandler.class
- .getName());
- fileLogger.setLevel(Level.INFO);
- Handler[] hs = fileLogger.getHandlers();
- for (Handler h : hs) {
- h.close();
- fileLogger.removeHandler(h);
- }
- try {
- // 文件 日志文件名为mylog 日志最大写入为4000个字节 保存5天内的日志文件
- // 如果文件没有达到规定大小则将日志文件添加到已有文件
- XLFileStreamHandler fh = new XLFileStreamHandler("d:\\mylog\\test",
- 200, 10, false);
- fh.setLevel(Level.OFF);
- fh.setEncoding("UTF-8");
- fh.setFormatter(new XLLogFormatter());
- fileLogger.setUseParentHandlers(false);
- fileLogger.addHandler(fh);
- } catch (Exception ex) {
- ex.printStackTrace();
- }
- for (int i = 0; i < 30; i++) {
- fileLogger.log(Level.INFO, "我被记录了吗?");
- }
- }
- }
package com.xunlei.demo.util; import java.io.BufferedOutputStream; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStream; import java.text.SimpleDateFormat; import java.util.Date; import java.util.HashMap; import java.util.Map; import java.util.TreeSet; import java.util.logging.Filter; import java.util.logging.Formatter; import java.util.logging.Handler; import java.util.logging.Level; import java.util.logging.LogManager; import java.util.logging.LogRecord; import java.util.logging.Logger; import java.util.logging.StreamHandler; /** * 自定义日志文件处理器---日期及文件大小存储,并自动清除过期日志文件 * * @author ZengDong * @since 2008-9-11下午11:16:39 */ public class XLFileStreamHandler extends StreamHandler { /** * 抄自FileHandler的实现,用于跟踪写入文件的字节数 这样以便提高效率 */ private class MeteredStream extends OutputStream { private OutputStream out; // 记录当前写入字节数 private int written; MeteredStream(OutputStream out, int written) { this.out = out; this.written = written; } public void close() throws IOException { out.close(); } public void flush() throws IOException { out.flush(); } public void write(byte buff[]) throws IOException { out.write(buff); written += buff.length; } public void write(byte buff[], int off, int len) throws IOException { out.write(buff, off, len); written += len; } public void write(int b) throws IOException { out.write(b); written++; } } private class XLLogFile extends File { private static final long serialVersionUID = 952141123094287978L; private Date date; private String dateString; private int sid; public int getSid() { return this.sid; } public void setSid(int sid) { this.sid = sid; } public Date getDate() { return this.date; } public void setDate(Date date) { this.date = date; } public String getDateString() { return this.dateString; } public void setDateString(String dateString) { this.dateString = dateString; } public int compareTo(File another) { XLLogFile ano = (XLLogFile) another; int dateComResult = date.compareTo(ano.getDate()); if (dateComResult == 0) { return sid - ano.getSid(); } return dateComResult; } SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); public XLLogFile(String pathname) { super(pathname); try { int dot = pathname.lastIndexOf('.'); int split = pathname.lastIndexOf(splitDateIndexChar); int underline = pathname.lastIndexOf('_'); dateString = pathname.substring(underline + 1, split); String numStr = pathname.substring(split + 1, dot); date = sdf.parse(dateString); sid = Integer.valueOf(numStr); } catch (Exception e) { System.err.println("log对应文件夹中包含了不符合XLLOG格式的文件!!"); e.printStackTrace(); } } } private static final String undifine = "xlcallcenter"; // 是否将日志写入已存在的日志文件中 private boolean append; // 保存几天之内的日志文件 // 时间间隔小于等于0时表明不删除历史记录 private int dateinterval = 5; // 保存存在的日志文件 private Map<String, TreeSet<XLLogFile>> files; // 每个日志希望写入的最大字节数,如果日志达到最大字节数则当天日期的一个新的编号的日志文件将被创建,最新的日志记录在最大编号的文件中 // 文件大小为小于等于0时表明不限制日志文件大小 private int limit = 1048576 * 5; // 输出流 private MeteredStream msOut; // 文件路径, 可以是个目录或希望的日志名称,如果是个目录则日志为"callcenter_zd" // 指定日志名称时不需要包括日期,程序会自动生成日志文件的生成日期及相应的编号 private String pattern = "./log/xunleidemo"; private char splitDateIndexChar = '#'; public XLFileStreamHandler() throws Exception { configure(); openWriteFiles(); } /** * 初始化自定义文件流处理器 * * @param fileUrl * 文件路径, 可以是个目录或希望的日志名称,如果是个目录则日志为"callcenter_zd" * 指定日志名称时不需要包括日期,程序会自动生成日志文件的生成日期及相应的编号 * @param limit * 每个日志希望写入的最大字节数,如果日志达到最大字节数则当天日期的一个新的编 * 号的日志文件将被创建,最新的日志记录在最大编号的文件中 * @param dateinterval * 保存几天之内的日志文件 * @param append * 是否将日志写入已存在的日志文件中 * @throws java.lang.Exception */ public XLFileStreamHandler(String fileUrl, int limit, int dateinterval, boolean append) throws Exception { super(); this.pattern = fileUrl; this.limit = limit; this.dateinterval = dateinterval; this.append = append; openWriteFiles(); } /** * 检查当前日志时间,删除过期日志 */ private void deleteExpiredLog() { try { // 今天作为基准 SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); String today = sdf.format(new Date().getTime()); // 删除过期日志 for (String keyDate : files.keySet()) { if ((sdf.parse(today).getTime() - sdf.parse(keyDate).getTime()) / (86400 * 1000) > dateinterval) { TreeSet<XLLogFile> traceDateFiles = files.get(keyDate); for (File deletingFile : traceDateFiles) { // if(deletingFile.exists()) { deletingFile.delete(); // } } files.remove(today); } } } catch (Exception ex) { Logger.getLogger(XLFileStreamHandler.class.getName()).log( Level.SEVERE, null, ex); } } // Private method to configure a FileHandler from LogManager // properties and/or default values as specified in the class // javadoc. private void configure() { LogManager manager = LogManager.getLogManager(); String cname = getClass().getName(); // 获得pattern pattern = manager.getProperty(cname + ".pattern"); if (pattern == null) { pattern = "./log/xunleidemo"; } // 获得limit String limitVal = manager.getProperty(cname + ".limit"); if (limitVal == null) { limit = 1048576 * 5; } else { try { limit = Integer.parseInt(limitVal.trim()); // if (limit < 0) { // limit = 1048576 * 5; // } } catch (Exception ex) { limit = 1048576 * 5; } } // 获得formatter String formatVal = manager.getProperty(cname + ".formatter"); if (formatVal == null) { setFormatter(new XLLogFormatter()); } else { try { Class clz = ClassLoader.getSystemClassLoader().loadClass( formatVal); setFormatter((Formatter) clz.newInstance()); } catch (Exception ex) { // We got one of a variety of exceptions in creating the // class or creating an instance. // Drop through. } } // 获得append String appendVal = manager.getProperty(cname + ".append"); if (appendVal == null) { append = false; } else { if (appendVal.equalsIgnoreCase("true") || appendVal.equals("1")) { append = true; } else if (appendVal.equalsIgnoreCase("false") || appendVal.equals("0")) { append = false; } } // 获得level String levelVal = manager.getProperty(cname + ".level"); if (levelVal == null) { setLevel(Level.ALL); } else { try { setLevel(Level.parse(levelVal.trim())); } catch (Exception ex) { setLevel(Level.ALL); } } // 获得dateinterval String dateintervalVal = manager.getProperty(cname + ".dateinterval"); if (dateintervalVal == null) { dateinterval = 5; } else { try { dateinterval = Integer.parseInt(dateintervalVal.trim()); if (dateinterval <= 0) { dateinterval = 5; } } catch (Exception ex) { dateinterval = 5; } } // 获得filter String filterVal = manager.getProperty(cname + ".filter"); if (filterVal == null) { setFilter(null); } else { try { Class clz = ClassLoader.getSystemClassLoader().loadClass( filterVal); setFilter((Filter) clz.newInstance()); } catch (Exception ex) { // We got one of a variety of exceptions in creating the // class or creating an instance. // Drop through. } } // 获得encoding String encodingVal = manager.getProperty(cname + ".encoding"); if (encodingVal == null) { try { setEncoding(null); } catch (Exception ex2) { // doing a setEncoding with null should always work. // assert false; } } else { try { setEncoding(encodingVal); } catch (Exception ex) { try { setEncoding(null); } catch (Exception ex2) { // doing a setEncoding with null should always work. // assert false; } } } } /** * 将离现在最近的文件作为写入文件的文件 例如 xunleidemo_2008-02-19#30.log * xunleidemo表示自定义的日志文件名,2008-02-19表示日志文件的生成日期,30 表示此日期的第30个日志文件 */ private void openLastFile(boolean append) { try { super.close(); SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); String today = sdf.format(new Date().getTime()); // 如果没有包含当天的日期,则添加当天日期的日志文件 boolean isFirstLogToday = false; if (!files.containsKey(today)) { String logIndex = today + splitDateIndexChar + 1; TreeSet<XLLogFile> todayFiles = new TreeSet<XLLogFile>(); todayFiles.add(getNewFile(logIndex)); files.put(today, todayFiles); isFirstLogToday = true; } // 获得今天最大的日志文件编号 XLLogFile todayLastFile = files.get(today).last(); int maxLogCount = todayLastFile.getSid(); String logIndex = today + splitDateIndexChar + (maxLogCount + (isFirstLogToday ? 0 : (append ? 0 : 1))); XLLogFile wantWriteFile = getNewFile(logIndex); files.get(today).add(wantWriteFile); openFile(wantWriteFile, append); } catch (Exception ex) { Logger.getLogger(XLFileStreamHandler.class.getName()).log( Level.SEVERE, null, ex); } } /** * 根据logIndex要建立File * * @param logIndex * 包含今天日期及编号,如2008-09-11#1 * @return File */ private XLLogFile getNewFile(String logIndex) { File file = new File(pattern); XLLogFile wantWriteFile = null; StringBuilder filePath = new StringBuilder(pattern); if (file.isDirectory()) { filePath.append(File.separator); filePath.append(undifine); } filePath.append('_'); filePath.append(logIndex); filePath.append(".log"); wantWriteFile = new XLLogFile(filePath.toString()); return wantWriteFile; } /** * 读取已经记录的日志的时间信息 */ private Map<String, TreeSet<XLLogFile>> getRecodedLog() { Map<String, TreeSet<XLLogFile>> filesMap = new HashMap<String, TreeSet<XLLogFile>>(); try { // 建立相关目录 File file = new File(pattern); File fileDir = null; if (pattern.endsWith("/") || pattern.endsWith("\\")) { // 是个目录 fileDir = file; if (!file.exists()) { file.mkdirs(); } } else { // 带了前缀 File parentFile = new File(file.getParent()); fileDir = parentFile; // 父目录不存在则新建目录 if (!parentFile.exists()) { parentFile.mkdirs(); } } // 加入到filesMap中 for (File contentFile : fileDir.listFiles()) { if (contentFile.isFile()) { XLLogFile newXLLogFile = new XLLogFile(contentFile .getAbsolutePath()); TreeSet<XLLogFile> fileListToDate = filesMap .get(newXLLogFile.getDateString()); if (fileListToDate == null) { fileListToDate = new TreeSet<XLLogFile>(); } fileListToDate.add(newXLLogFile); filesMap.put(newXLLogFile.getDateString(), fileListToDate); } } files = filesMap; return filesMap; } catch (Exception ex) { Logger.getLogger(XLFileStreamHandler.class.getName()).log( Level.SEVERE, null, ex); } return null; } /** * 打开需要写入的文件 * * @param file * 需要打开的文件 * @param append * 是否将内容添加到文件末尾 */ private void openFile(File file, boolean append) throws Exception { int len = 0; if (append) { len = (int) file.length(); } FileOutputStream fout = new FileOutputStream(file.toString(), append); BufferedOutputStream bout = new BufferedOutputStream(fout); msOut = new MeteredStream(bout, len); setOutputStream(msOut); } /** * 获得将要写入的文件 */ private synchronized void openWriteFiles() throws Exception { if (!getLevel().equals(Level.OFF)) { getRecodedLog(); deleteExpiredLog(); openLastFile(append); } } /** * 发布日志信息 */ public synchronized void publish(LogRecord record) { super.publish(record); super.flush(); if (getLevel().equals(Level.OFF)) { return; } if (limit > 0 && msOut.written >= limit) { openLastFile(false); } } public static void main(String[] args) { Logger fileLogger = Logger.getLogger(XLFileStreamHandler.class .getName()); fileLogger.setLevel(Level.INFO); Handler[] hs = fileLogger.getHandlers(); for (Handler h : hs) { h.close(); fileLogger.removeHandler(h); } try { // 文件 日志文件名为mylog 日志最大写入为4000个字节 保存5天内的日志文件 // 如果文件没有达到规定大小则将日志文件添加到已有文件 XLFileStreamHandler fh = new XLFileStreamHandler("d:\\mylog\\test", 200, 10, false); fh.setLevel(Level.OFF); fh.setEncoding("UTF-8"); fh.setFormatter(new XLLogFormatter()); fileLogger.setUseParentHandlers(false); fileLogger.addHandler(fh); } catch (Exception ex) { ex.printStackTrace(); } for (int i = 0; i < 30; i++) { fileLogger.log(Level.INFO, "我被记录了吗?"); } } }
附带用到的
日志格式
- package com.xunlei.demo.util;
- import java.io.PrintWriter;
- import java.io.StringWriter;
- import java.text.DecimalFormat;
- import java.util.Calendar;
- import java.util.logging.LogRecord;
- /**
- * Print a brief summary of the LogRecord in a human readable. The summary will
- * typically be on a single line (unless it's too long :) ... what I meant to
- * say is that we don't add any line breaks).
- *
- * @author ZengDong
- */
- public class XLLogFormatter extends java.util.logging.Formatter {
- private static String lineSeparator = System.getProperty("line.separator");
- static long startTime = System.currentTimeMillis();
- private static DecimalFormat threeDigFmt = new DecimalFormat("000");
- private static DecimalFormat twoDigFmt = new DecimalFormat("00");
- /**
- * Format the given LogRecord.
- *
- * @param record
- * the log record to be formatted.
- * @return a formatted log record
- */
- // private final static String format = "{0,date} {0,time}";
- // private MessageFormat formatter;
- // Date dat = new Date();
- // private Object args[] = new Object[1];
- public synchronized String format(LogRecord record) {
- StringBuilder sb = new StringBuilder();
- // dat.setTime(record.getMillis());
- // args[0] = dat;
- // StringBuffer text = new StringBuffer();
- // if (formatter == null) {
- // formatter = new MessageFormat(format);
- // }
- // formatter.format(args, text, null);
- // sb.append(text);
- // current time
- // Calendar cal = Calendar.getInstance();
- // int millis = cal.get(Calendar.MILLISECOND);
- // sb.append('.').append(threeDigFmt.format(millis)).append(' ');
- // current time
- Calendar cal = Calendar.getInstance();
- int hour = cal.get(Calendar.HOUR_OF_DAY);
- int minutes = cal.get(Calendar.MINUTE);
- int seconds = cal.get(Calendar.SECOND);
- int millis = cal.get(Calendar.MILLISECOND);
- sb.append(twoDigFmt.format(hour)).append(':');
- sb.append(twoDigFmt.format(minutes)).append(':');
- sb.append(twoDigFmt.format(seconds)).append('.');
- sb.append(threeDigFmt.format(millis)).append(' ');
- // log level
- sb.append(record.getLevel().getLocalizedName());
- sb.append(": ");
- // caller method
- int lineNumber = inferCaller(record);
- String loggerName = record.getLoggerName();
- if (loggerName == null)
- loggerName = record.getSourceClassName();
- if (loggerName.startsWith("com.xunlei.callcenter.")) {
- sb.append(loggerName.substring("com.xunlei.callcenter.".length()));
- } else
- sb.append(record.getLoggerName());
- if (record.getSourceMethodName() != null) {
- sb.append('.');
- sb.append(record.getSourceMethodName());
- // include the line number if we have it.
- if (lineNumber != -1)
- sb.append("().").append(Integer.toString(lineNumber));
- else
- sb.append("()");
- }
- sb.append(' ');
- sb.append(record.getMessage());
- sb.append(lineSeparator);
- if (record.getThrown() != null) {
- try {
- StringWriter sw = new StringWriter();
- PrintWriter pw = new PrintWriter(sw);
- record.getThrown().printStackTrace(pw);
- pw.close();
- sb.append(sw.toString());
- } catch (Exception ex) {
- }
- }
- return sb.toString();
- }
- /**
- * Try to extract the name of the class and method that called the current
- * log statement.
- *
- * @param record
- * the logrecord where class and method name should be stored.
- *
- * @return the line number that the call was made from in the caller.
- */
- private int inferCaller(LogRecord record) {
- // Get the stack trace.
- StackTraceElement stack[] = (new Throwable()).getStackTrace();
- // the line number that the caller made the call from
- int lineNumber = -1;
- // First, search back to a method in the XLCallCenter Logger class.
- int ix = 0;
- while (ix < stack.length) {
- StackTraceElement frame = stack[ix];
- String cname = frame.getClassName();
- if (cname.equals("com.xunlei.demo.util.Logger")) {
- break;
- }
- ix++;
- }
- // Now search for the first frame before the XLCallCenter Logger class.
- while (ix < stack.length) {
- StackTraceElement frame = stack[ix];
- lineNumber = stack[ix].getLineNumber();
- String cname = frame.getClassName();
- if (!cname.equals("com.xunlei.demo.util.Logger")) {
- // We've found the relevant frame.
- record.setSourceClassName(cname);
- record.setSourceMethodName(frame.getMethodName());
- break;
- }
- ix++;
- }
- return lineNumber;
- }
- }
发表评论
-
使用cmd命令关机或重启电脑[回钦波转]
2013-04-25 12:23 1133dos cmd重启2003命令shutdow ... -
libyaml源代码在linux下解压、安装及试用
2012-07-06 16:39 2451libyaml源代码在linux下解压、安装及试用 ... -
【java】AES加密解密|及Base64的使用 [转]
2012-03-31 16:52 1334今天在网上看到一篇不错的博客,里面讲到加密及解密的信息。其实我 ... -
JAVA正则表达式经典实例教程[huiqinbo]
2012-03-22 14:38 1806归纳者 : huiqinboaddress : bei ... -
Java多线程同步Synchronized使用并详细分析与实例 【huiqinbo转于网络并总结】
2012-03-09 13:55 3087一.Synchronized基本知识: 在 ... -
从12306火车购票网站谈海量事务高速处理系统
2012-02-16 10:43 1921JE上好多讨论这个主题的帖子,但是水(v)的人远远多于技术讨论 ... -
今天闲谈下最近写的正则表达式方法,对初学者来说绝对实用【回钦波】
2012-02-03 18:38 872////////////////// test1 ... -
获得到当前方法及类的名字Thread.currentThread().getStackTrace()[0].getClassName();
2011-09-26 13:22 2231获得到当前方法及类的名字: Thread.curren ... -
BufferedReader和BufferedOutputStream之间的灵活应用【回钦波】
2011-09-16 17:44 1069package log; import java.io.Bu ... -
获取c盘下的用户地址System.getProperty("user.home")
2011-09-15 17:09 1143System.getProperty("user.h ... -
jdk log自定义配置文件【回钦波写于20110915】
2011-09-15 17:00 1196import java.io.IOException; ... -
获得本类(java文件)的路径【huiqinbo】this.getClass().getResource("/").getPath()
2011-09-14 15:29 1352package com.huiqinbo; imp ... -
java中ArrayList 、LinkList区别【huiqinbo】
2011-09-08 11:42 1237java中ArrayList 、LinkList、List区 ... -
jdk的logging实例入门学习
2011-09-07 16:40 1006jdk的logging实例入门学习 分类: JDK 2 ... -
关于数组new 与不new 的问题
2011-08-30 15:05 861public class Test { String c ... -
Eclipse快捷键大全(huiqinbo)
2011-08-30 11:12 771Ctrl+1 快速修复(最经典 ... -
oracle数据库左右内外连接 【回钦波详解】
2011-08-29 15:00 1193oracle数据库左右内外连 ... -
@SuppressWarnings("**")是什么意思【回钦波详细解答】
2011-08-10 10:55 1004很多网友问我(回钦 ... -
很好用的Java反编译软件【回钦波】
2011-04-29 16:49 1067有Windows,Linux和Mac OS三个版本可 ... -
JAVA进制等移位运算[参考于回钦波文库]
2010-12-20 14:33 1049JAVA移位运算符 文章分类:Java编程 作者:回钦波 ...
相关推荐
在Swing应用中,我们同样可以使用Java内置的`java.util.logging`包来输出错误日志。这篇文档主要讨论了如何在Java Swing应用中使用`Logger`来生成和管理错误日志。 `Logger`是Java的日志记录工具,它提供了多种级别...
`Logger`是Java标准库`java.util.logging`包提供的日志工具,它提供了多种级别的日志记录,如`SEVERE`、`WARNING`、`INFO`、`CONFIG`、`FINE`、`FINER`和`FINEST`。本篇文章将深入探讨Java中的`Logger`封装,以及...
例如,添加`java.util.logging.FileHandler.pattern`和`java.util.logging.FileHandler.limit`等属性,设置日志文件的命名规则(例如包含日期)以及每个文件的最大大小。 重起Tomcat后,新的配置才会生效。这意味着...
`logging.properties`文件用于配置Java原生日志工具的行为,包括日志输出的目的地、格式以及过滤规则等。默认情况下,Java安装目录下的`jre/lib/logging.properties`文件会被用来初始化日志系统。 ##### 4.1 读取...
2. **使用Java Util Logging (JUL)**:这是Java内置的日志框架,可以设置系统属性(如`java.util.logging.LogManager.config`指向配置文件路径)或直接调用`Logger`类的方法来控制日志级别。例如,你可以使用`java....
比如,`java.util.logging`的配置文件是`logging.properties`,其中定义了日志级别、处理器和输出格式等。开发者可以通过指定`java.util.logging.config.file`属性来使用自定义的配置文件。其他框架如Log4j和Logback...
6. **格式化日志**:可以创建`SimpleFormatter`或自定义`Formatter`来控制日志输出的格式。例如: ```java SimpleFormatter formatter = new SimpleFormatter(); fileHandler.setFormatter(formatter); ``` 7. ...
`MySimpleFormatter.java`可能定义了一个简单的日志格式化器,继承自`java.util.logging.Formatter`,并覆盖`format(LogRecord)`方法,以自定义日志输出的样式。默认的`SimpleFormatter`会输出一条简洁的消息,但...
总结来说,JavaUtil日志提供了一套完整的日志管理方案,包括创建日志记录器、设置处理器以及定制日志格式,使得开发者能够根据需求灵活地调整日志的输出方式和内容。在实际开发中,合理使用这些功能可以帮助调试、...
Juli,全称为Java Util Logging,是Tomcat自定义的日志框架,它取代了早期版本中的Apache Commons Logging。Juli提供了更高效、更可控的日志处理机制,允许开发者针对不同的日志需求进行精细化配置。与Java内置的...
4. **格式化日志**:JDK提供了`java.util.logging.Formatter`类,用于控制日志消息的输出格式。我们可以创建自定义的Formatter,以满足特定的格式需求,比如添加时间戳、线程ID、类名等信息。 5. **使用第三方日志...
在Java中实现syslog日志发送,我们可以使用开源库如`logback`或`java.util.logging`。以`logback`为例,我们需要配置`logback.xml`,添加一个syslog appender: ```xml <appender name="SYSLOG" class="ch.qos....
1. **Logger**: Ibatis提供了一个日志接口`org.apache.ibatis.logging.Log`,而`ibatis.util.LogFactory`则负责根据用户配置的实现(如Log4j、SLF4J或Java内置的日志系统)创建对应的日志实例,用于记录SQL执行和...
它的配置文件通常为logback.xml,同样支持多级别的日志输出和自定义布局。 3. **Java.util.logging**: Java内置的日志框架,简洁且易于集成。尽管功能相对较弱,但在小型项目或不希望引入额外依赖的场合,它是不错...
例如,`java.util.logging.ConsoleHandler`负责将日志输出到控制台,而`java.util.logging.FileHandler`则将日志写入文件。 5. **日志级别配置** - 通过调整日志级别的设置,可以控制哪些级别的信息被记录。例如,...
- **自定义处理器**:可以继承`java.util.logging.Handler`类,实现自己的日志处理逻辑。 5. **过滤器(Filter)** - **控制日志输出**:通过实现`java.util.logging.Filter`接口,可以过滤特定的日志事件,只让...
这个XML文件可能包含了日志记录级别设置、日志处理器(如控制台、文件或网络)的选择、过滤器的定义以及日志输出格式等。例如,你可以指定哪些类或包的日志应该被记录,以及这些日志应如何处理和存储。 在JDK的`...
在Java Web应用开发中,Tomcat作为常用的Servlet容器,其默认的日志系统是通过`catalina.out`文件记录所有标准输出和错误输出。当应用运行一段时间后,`catalina.out`文件可能会变得非常大,占用大量磁盘空间,这...
3. 日志配置:Java日志系统可以通过配置文件(如logging.properties)来定制日志的行为,如日志输出的格式、级别、处理器等。 二、常见Java日志框架 1. Log4j:Apache的Log4j是Java中最广泛使用的日志框架,提供了...
Spring Boot默认集成了多个流行的日志框架,如Logback、Log4j2和Java Util Logging(JUL)。其中,Logback是Spring Boot的默认日志系统,因为它在性能和灵活性方面表现优秀。如果想切换到其他日志框架,可以通过排除...