PrintStream类的学习与多目的地输出重定向问题
来源:互联网 发布:淘宝卓辰数码是真是假 编辑:程序博客网 时间:2024/05/05 23:27
最近开发的Dodo工具箱中需要一个日志功能,当然现在已经有很成熟很好用的Log4j,但是我觉得作为一个菜鸟,有必要自己开发一个简单的日志处理模块。下面简介该模块的设计与输出重定向这个难点。
用例设计:
类设计:
实现难点——输出重定向:
我是这样设想的,日志来源于三个方面 1其他模块使用Logger记录的日志信息 2 系统执行过程中需要输出的信息 3 系统在运行过程中碰到的错误信息。日志输出的目的也有三个地方,第一:控制台 第二:日志文件 第三:gui即时信息窗口。
如果只是单目的地的重定向十分简单,比如说想把System.err的信息重定向到文件out,只需在系统启动时调用如下两行即可:
PrintStream out = new PrintStream(new BufferedOutputStream(new FileOutputStream("out")));System.setErr(out);
现在的难点在于需要将错误信息输出到多个目的地(文件,控制台,gui窗口),没有一个适合的PrintStream的子类来完成这个任务,那么我们就需要继承PrintStream,并在这个子类中重新print方法来完成我们的输出逻辑,我定义的该类的名称为IORedirect,该类的源码如下:
package toolBox.core.utility;import java.io.FileNotFoundException;import java.io.PrintStream;import java.util.Date;import java.util.Vector;import com.ibm.icu.text.SimpleDateFormat;/** * The class pipelines print/println's to several PrintStream. Useful for * directing system.out and system.err to external files etc. * * @author jiangkai * */public class IORedirect extends PrintStream {protected static SimpleDateFormat dateformat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");/**The default target output stream*/protected PrintStream default_target=null;/**The different target output streams*/protected Vector<PrintStream> targets=null;/** */protected Vector<Boolean> appendHeader = null;/** */protected String prefix = null;/** * initializes the object, with a default printstream. */public IORedirect(PrintStream s) {this(s,"defaultoutput");}public IORedirect(PrintStream s,String p){super(s);default_target = s;prefix = p;targets = new Vector<PrintStream>();appendHeader = new Vector<Boolean>();clear();}/** * removes all streams and places the default printstream, if any, again in * the list. * * @see #getDefault() */public void clear() {targets.clear();appendHeader.clear();if (getDefault() != null){targets.add(getDefault());appendHeader.add(true);}}/** * returns the default printstrean, can be NULL. * * @return the default printstream * @see #m_Default */public PrintStream getDefault() {return default_target;}public void defaultPrint(String x){if(default_target!=null)default_target.print(x);}public void defaultPrintln(String x){if(default_target!=null)default_target.println(x);}/** * adds the given PrintStream to the list of streams, with NO timestamp and * NO prefix. * * @param p * the printstream to add */public void addPrintStream(PrintStream p) {addPrintStream(p,false);}public void addPrintStream(PrintStream p,boolean ah){if (!targets.contains(p)){targets.add(p);appendHeader.add(ah);}}public void removePrintStream(PrintStream p) {if (targets.contains(p)){int index = targets.indexOf(p);targets.remove(index);appendHeader.remove(index);}}public boolean containsPrintStream(PrintStream p) {return targets.contains(p);}public int size() {return targets.size();}public void flush() {for (PrintStream element : targets)element.flush();}protected void printHeader(){for(PrintStream element:targets)if(appendHeader.get(targets.indexOf(element)))element.print(dateformat.format(new Date())+" "+prefix+"\n\t");}@Overridepublic void print(int x) {printHeader();for (PrintStream element : targets)element.print(x);flush();}@Overridepublic void print(long x) {printHeader();for (PrintStream element : targets)element.print(x);flush();}@Overridepublic void print(float x) {printHeader();for (PrintStream element : targets)element.print(x);flush();}@Overridepublic void print(double x) {printHeader();for (PrintStream element : targets)element.print(x);flush();}@Overridepublic void print(boolean x) {printHeader();for (PrintStream element : targets)element.print(x);flush();}@Overridepublic void print(char x) {printHeader();for (PrintStream element : targets)element.print(x);flush();}@Overridepublic void print(char[] x) {printHeader();for (PrintStream element : targets)element.print(x);flush();}@Overridepublic void print(String x) {printHeader();for (PrintStream element : targets)element.print(x);flush();}@Overridepublic void print(Object x) {printHeader();for (PrintStream element : targets)element.print(x);flush();}@Overridepublic void println(int x) {printHeader();for (PrintStream element : targets)element.println(x);flush();}@Overridepublic void println(long x) {printHeader();for (PrintStream element : targets)element.println(x);flush();}@Overridepublic void println(float x) {printHeader();for (PrintStream element : targets)element.println(x);flush();}@Overridepublic void println(double x) {printHeader();for (PrintStream element : targets)element.println(x);flush();}@Overridepublic void println(boolean x) {printHeader();for (PrintStream element : targets)element.println(x);flush();}@Overridepublic void println(char x) {printHeader();for (PrintStream element : targets)element.println(x);flush();}@Overridepublic void println(char[] x) {printHeader();for (PrintStream element : targets)element.println(x);flush();}@Overridepublic void println(String x) {printHeader();for (PrintStream element : targets)element.println(x);flush();}@Overridepublic void println(Object x) {printHeader();for (PrintStream element : targets)element.println(x);flush();}/** * Writes <code>len</code> bytes from the specified byte array starting at * offset <code>off</code> to this stream. If automatic flushing is enabled * then the <code>flush</code> method will be invoked. * * <p> * Note that the bytes will be written as given; to write characters that * will be translated according to the platform's default character * encoding, use the <code>print(char)</code> or <code>println(char)</code> * methods. * * @param buf * A byte array * @param off * Offset from which to start taking bytes * @param len * Number of bytes to write */public void write(byte buf[], int off, int len) {for (PrintStream element : targets)element.write(buf, off, len);flush();}/** * Writes the specified byte to this stream. If the byte is a newline and * automatic flushing is enabled then the <code>flush</code> method will be * invoked. * * <p> * Note that the byte is written as given; to write a character that will be * translated according to the platform's default character encoding, use * the <code>print(char)</code> or <code>println(char)</code> methods. * * @param b * The byte to be written * @see #print(char) * @see #println(char) */public void write(int b) {for (PrintStream element : targets)element.write(b);flush();}public static void main(String[] args) throws FileNotFoundException{IORedirect stdRedirect = new IORedirect(System.err,"stderr");//stdRedirect.addPrintStream(System.err);System.setErr(stdRedirect);System.err.println("error");//stdRedirect.addPrintStream(System.out);//System.setOut(stdRedirect);//System.out.println("no");}}现在一目了然了,我们的输出逻辑在于重写PrintStream类中的Print函数,在该函数中我们自己定义需要向那写输出流输出日志信息,我在这里的写法是
@Overridepublic void println(boolean x) {printHeader();for (PrintStream element : targets)element.println(x);flush();}对于targets中的每一个输出流输出信息,当然,你可以在这边直接写文件输出的逻辑,窗口输出的逻辑,但是当前这种写法使得IORedirect这个类更加通用,不管你是什么输出流,只要注册到该IORediect类即可。
下面贴出该类的使用办法:
IORedirect stdoutRedirect = new IORedirect(System.out, "stdout");System.setOut(stdoutRedirect);stdoutRedirect.addPrintStream(m_windowStream, true);stdoutRedirect.addPrintStream(m_FileStream,true);
这样,即将m_windowStream和m_FileStream注册到了该重定向对象中,这样系统的输出会输出到m_windowStream和m_FileStream这两个输出流中去,当然了,m_windowStream和m_FileStream也必须是PrintStream的子类,关于写法很简单,这里不再啰嗦。
- PrintStream类的学习与多目的地输出重定向问题
- Linux学习笔记--输出重定向与输入重定向
- 重定向输出遇到的缓冲问题
- 重定向输出遇到的缓冲问题 .
- Linux中重定向输出的学习
- log4j 输出的目的地
- 重定向输入与输出
- 重定向与转发的问题
- 关于记录Snort的执行情况,输出信息重定向问题
- Linux 标准输出重定向 缺失的问题
- java的输出在命令行中的重定向问题
- 批处理文件的输出重定向
- Linux的输出重定向
- 输出流的重定向
- 重定向的输出不见了?
- vs 项目生成输出目的地只读问题的解决方法..
- 管道与IO重定向之输出重定向
- python 调用smtplib输出重定向问题
- Designer process terminated unexpectedly 问题的解决方法
- chrome源代码目录结构简介
- WampServer启动失败
- 酷站60个漂亮可用的外文站点欣赏(经典推荐)
- 如何在arcgis javascript api viewer使用配置文件
- PrintStream类的学习与多目的地输出重定向问题
- Quartz调度器堵塞原理和解决
- 高级Bash脚本编程指南--网页版
- 利用GDB调试CORE文件
- asp.net基于数据库表的缓存实例
- Linux Socket编程(不限Linux)
- android system/bin 命令
- 关于p3p 简洁策略,以及浏览器的支持情况
- Ms Sqlserver与Oralce取得表的列信息与外键信息