All Downloads are FREE. Search and download functionalities are using the official Maven repository.

net.gdface.utils.SimpleLog Maven / Gradle / Ivy

There is a newer version: 3.2.1
Show newest version
package net.gdface.utils;

import java.io.PrintStream;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;


/**
 * 简单日志输出工具类
 * @author guyadong
 *
 */
public class SimpleLog {
	/** 占位符 */
	private static final String DELIM_STR = "(\\{\\}|%s)";
	private static final Object[] EMPTY_ARGS = new Object[0];
	private final static OutputString outputString = createOutputString();
	private static OutputString createOutputString() {
		if(Platform.isAndroid()){
			return new AndroidOutput();
		}else {
			return new StandardOutput();
		}
	}
	/**
	 * 返回格式化的日志信息字符串
* example: *
	 * logString("name : {},age:{}","tom",23);
	 * 
* @param format 格式字符串,采用"{}"或"%s"为占位符 * @param args 填充占位符的参数列表,如果数量小于占位符个数则多出的占位符填充"null" */ public static String logString(String format, Object ... args){ if(null == format){ return ""; } if(null == args){ args = EMPTY_ARGS; } StringBuilder buffer = new StringBuilder(format.length() + 64); int beginIndex = 0,count = 0; Pattern pattern = Pattern.compile(DELIM_STR); Matcher matcher = pattern.matcher(format); while(matcher.find()){ buffer.append(format.substring(beginIndex,matcher.start())); try{ buffer.append(args[count++]); }catch(IndexOutOfBoundsException e){ // 数组越界时对应占位符填null buffer.append("null"); } beginIndex = matcher.end(); } buffer.append(format.substring(beginIndex,format.length())); return buffer.toString(); } public static void log(PrintStream printStream,int level, String format, Object ... args){ if(null == printStream){ return; } Thread currentThread = Thread.currentThread(); StackTraceElement stackTrace = currentThread.getStackTrace()[level]; printStream.printf("[%s] (%s:%d) %s\n", currentThread.getName(), stackTrace.getFileName(), stackTrace.getLineNumber(), logString(format,args)); } public static void log(OutputString outputString,Level level,String format, Object ... args){ if(null == outputString){ return; } Thread currentThread = Thread.currentThread(); StackTraceElement stackTrace = currentThread.getStackTrace()[outputString.stackLeve()]; outputString.log(level, String.format("[%s] (%s:%d) %s %s\n", currentThread.getName(), stackTrace.getFileName(), stackTrace.getLineNumber(), stackTrace.getMethodName(), logString(format,args))); } /** * 向{@code printStream}输出日志信息
* example: *
	 * log("name : {},age:{}","tom",23);
	 * 
* @param printStream * @param format 格式字符串,采用"{}"或"%s"为占位符,占位符个数要与{@code args}数组长度匹配 * @param args 填充占位符的参数列表,如果数量小于占位符个数则多出的占位符填充"null" */ public static void log(PrintStream printStream,String format, Object ... args){ log(printStream,3,format,args); } /** * @param output 是否输出 * @param printStream * @param format 格式字符串 * @param args 填充占位符的参数列表 * @see #log(PrintStream, String, Object...) */ public static void log(boolean output,PrintStream printStream,String format, Object ... args){ if(output){ log(printStream,3,format,args); } } private static final String formatByCount(int c){ StringBuffer buffer = new StringBuffer(); for(int i=0;i0){ buffer.append(","); } buffer.append("{}"); } return buffer.toString(); } /** * 向控制台输出日志信息
* @param arg * @see #log(OutputString, Level, String, Object...) */ public static void logObjects(Object arg){ log(outputString,Level.INFO,formatByCount(1),new Object[]{arg}); } /** * 向控制台输出日志信息
* @param arg * @param args * @see #log(PrintStream, String, Object...) */ public static void logObjects(Object arg,Object ... args){ Object[] array = new Object[args.length+1]; array[0] = arg; System.arraycopy(args, 0, array, 1, args.length); log(outputString,Level.INFO,formatByCount(args.length),array); } /** * 向控制台输出日志信息
* @param format 格式字符串,采用"{}"或"%s"为占位符 * @param args * @see #log(OutputString, Level, String, Object...) */ public static void log(String format, Object ... args){ log(outputString,Level.INFO,format,args); } /** * 向控制台输出日志信息
* @param output 是否输出 * @param format 格式字符串,采用"{}"或"%s"为占位符 * @param args * @see #log(OutputString, Level, String, Object...) */ public static void log(boolean output,String format, Object ... args){ if(output){ log(outputString,Level.INFO,format,args); } } public static void log(String msg,Throwable e){ log(outputString,Level.ERROR,"{}\n{}",msg,stackTraceOf(e)); } public static void log(Throwable e){ log(outputString,Level.ERROR,"{}",stackTraceOf(e)); } public static final String stackTraceOf(Throwable e){ if(e == null){ e = new NullPointerException("e is null"); } StringWriter writer = new StringWriter(); PrintWriter pw = new PrintWriter(writer); e.printStackTrace(pw); return writer.toString(); } /** * @author guyadong * @see 2.8.0 */ enum Level{ INFO,ERROR } /** * 消息输出接口
* 应用层通过实现此接口实现日志输出 * @see StandardOutput * @see AndroidOutput * @author guyadong * @see 2.8.0 */ static interface OutputString{ /** * 日志信息输出 * @param level 日志输出类型 * @param message 待输出日志信息 */ void log(Level level, String message); /** * 返回输出行号类名所需要的堆栈级数 */ int stackLeve(); } /** * 基于标准控制台输出的{@link OutputString}实现 * @author guyadong * @see 2.8.0 */ static class StandardOutput implements OutputString{ final Mapstreams; public StandardOutput() { streams = new HashMap<>(); streams.put(Level.INFO, System.out); streams.put(Level.ERROR, System.err); } @Override public void log(Level level, String message) { streams.get(level).print(String.valueOf(message)); } @Override public int stackLeve() { return 3; } } /** * android平台日志(android.util.Log)控制台输出的{@link OutputString}实现
* 非android平台调用会抛出{@link RuntimeException}异常 * @author guyadong * @see 2.8.0 */ static class AndroidOutput implements OutputString{ /** 默认日志标签 */ public static final String DEFAULT_TAG = "SIMPLE_LOG"; private final String defaultTag; private final Mapmethods; /** * 构造方法 * @param defaultTag 日志输出标签名,为{@code null}使用默认值{@link #DEFAULT_TAG} */ public AndroidOutput(String defaultTag){ methods = new HashMap<>(); this.defaultTag = (null == defaultTag) ? DEFAULT_TAG : defaultTag; methods.put(Level.INFO, methodOfLog("i")); methods.put(Level.ERROR, methodOfLog("e")); } /** * 使用默认日志标签的构造方法 */ public AndroidOutput() { this(null); } /** 反射方式获取 Log的指定方法 方法 */ static Method methodOfLog(String name) { try { Class logClass = Class.forName("android.util.Log"); return logClass.getMethod(name, String.class,String.class); } catch (ClassNotFoundException e) { throw new UnsupportedOperationException("UNSUPPORTED PLATFORM,android reqiured"); } catch (Exception e) { throw new RuntimeException(e); } } @Override public void log(Level level, String message) { try { methods.get(level).invoke(null, defaultTag,String.valueOf(message)); } catch (InvocationTargetException e) { throw new RuntimeException(e.getTargetException()); }catch (Exception e) { throw new RuntimeException(e); } } @Override public int stackLeve() { return 4; } } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy