文档章节

拦截System.out和System.err

markdrord
 markdrord
发布于 2015/03/02 18:16
字数 414
阅读 19
收藏 0

System.out和System.err是Java的默认输出,大家对此都是非常熟悉的,但是你想过如何对他们进行拦截,而将输入转移到其他位置吗?

你可能想只需要对System.out和System.err做一个代理就好了,ok,就是这么回事,然后通过System.setOut和System.setErr方法将代理传给JVM,但是到底怎么做呢?因为他们的类型是java.io.PrintStream,是不是写一个类PrintStreamProxy代理所有的public方法就行了呢,如果你阅读了源代码的话会发现这样做会遇到很多问题,具体什么问题大家试一试就知道了,本文说的是另外一种代理。

因为java.io.PrintStream有一个是用java.OutputStream的构造方法,所有的输出最终都是通过OutputStream完成的,所有拦截它可以达到同样的效果。

下面就是代码了:

abstract class Monitor extends OutputStream {

		private PrintStream real;
		private List<Byte> buffer;

		private char lineChar;

		public Monitor(PrintStream printStream) {
			this.real = printStream;
			this.buffer = this.createByteBuffer ();
			String s = System.getProperty("line.separator");
			lineChar = s.charAt(s.length() -1);
		}

		PrintStream getReal() {
			return real;
		}

		@Override
		synchronized
		public void write(int b) throws IOException {
			buffer.add(Integer.valueOf(b).byteValue());

			if (b == lineChar) {
				String line = makeString();
				LogLine obj = createObject(line);
				Event event = new Event(Monitor.this, obj);
				try {
					publisher.publish(event);
				} catch (Throwable t) {
					onError(t, line);
				} finally {
					real.print(line);
				}
			}
		}

		protected String makeString() {
			byte[] bs = new byte[buffer.size()];
			for (int i=0; i<buffer.size(); i++) {
				bs[i] = buffer.get(i);
			}
			String str = new String(bs);
			buffer = this.createByteBuffer ();
			return str;
		}

		protected List<Byte> createByteBuffer () {
			return new ArrayList<Byte>(200);
		}

		protected abstract LogLine createObject(String str);

		protected void onError(Throwable t, String str) {

		}

	}

通过代码可以知道只需要代理java.io.OutputStream的write方法就可以了,并且可以将每次输出的一行字符串发送给外界。

如果要代理System.out可以这样写

System.setOut(new PrintStream(new Monitor(){
	...
}));


© 著作权归作者所有

共有 人打赏支持
markdrord
粉丝 1
博文 7
码字总数 2329
作品 0
浦东
技术主管
System.out.println与System.err.println的区别

1、System.out.println 能重定向到别的输出流,这样的话你在屏幕上将看不到打印的东西了, 而System.err.println只能在屏幕上实现打印,即使你重定向了也一样。 System.setOut(new PrintStr...

Sandy_wu
2013/03/22
0
0
hadoop 2.6 mapreduce 自定义log 的查看方法

作者 用的 hadoop 2.6.0 其它版本的忘记了 看不到的log 在我们平时的hadoop mapreduce 运行中 大家都会发现 不管在mapreduce 中用 System.out 还是System.err,还是log4j 等等 在yarn 下图中...

疯code
2016/08/18
11
0
System.err与System.out的不同?

同时使用System.err和System.out,得到的输出结果顺序不一样,两者有什么区别?

蜡_小新
2016/07/28
626
9
安卓学习之三种输出日志信息方法

①日志优先级:ERROR>WARN>INFO>DEBUG>UERBOSE ②private static final String TAG="LogTest"; String msg="liang"; 第一种:Log.i(TAG,msg); tag为TAG,级别是Info 第二种:System.out.print......

湖心亭看雪
2014/06/13
0
0
Android查看stdout 和stderr

在默认状态下,Android系统有stdout和stderr(System.out和System.err)输出到/dev/null,在运行Dalvik VM的进程中,有一个系统可以备份日志文件。在这种情况下,系统会用stdout和stderr和优先...

shouyong
2013/01/17
0
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

深夜胡思乱想

魔兽世界 最近魔兽世界出了新版本, 周末两天升到了满级,比之前的版本体验好很多,做任务不用抢怪了,不用组队打怪也是共享拾取的。技能简化了很多,哪个亮按哪个。 运维 服务器 产品 之间的...

Firxiao
8分钟前
0
0
MySQL 8 在 Windows 下安装及使用

MySQL 8 带来了全新的体验,比如支持 NoSQL、JSON 等,拥有比 MySQL 5.7 两倍以上的性能提升。本文讲解如何在 Windows 下安装 MySQL 8,以及基本的 MySQL 用法。 下载 下载地址 https://dev....

waylau
42分钟前
0
0
微信第三方平台 access_token is invalid or not latest

微信第三方开发平台code换session_key说的特别容易,但是我一使用就带来无穷无尽的烦恼,搞了一整天也无济于事. 现在记录一下解决问题的过程,方便后来人参考. 我遇到的这个问题搜索了整个网络也...

自由的开源
今天
0
0
openJDK之sun.misc.Unsafe类CAS底层实现

注:这篇文章参考了https://www.cnblogs.com/snowater/p/8303698.html 1.sun.misc.Unsafe中CAS方法 在sun.misc.Unsafe中CAS方法如下: compareAndSwapObject(java.lang.Object arg0, long a......

汉斯-冯-拉特
今天
2
0
设计模式之五 责任链模式(Chain of Responsibility)

一. 场景 相信我们都有过这样的经历; 我们去职能部门办理一个事情,先去了A部门,到了地方被告知这件事情由B部门处理; 当我们到了B部门的时候,又被告知这件事情已经移交给了C部门处理; ...

JackieRiver
今天
1
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部