文档章节

拦截System.out和System.err

markdrord
 markdrord
发布于 2015/03/02 18:16
字数 414
阅读 22
收藏 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
浦东
技术主管
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.out.println与System.err.println的区别

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

Sandy_wu
2013/03/22
0
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

没有更多内容

加载失败,请刷新页面

加载更多

linux使用ntfs-3g操作ntfs格式硬盘

Linux内核目前只支持对微软NTFS文件系统的读取。 NTFS-3G 是微软 NTFS 文件系统的一个开源实现,同时支持读和写。NTFS-3G 开发者使用 FUSE 文件系统来辅助开发,同时对可移植性有益。 安装 ...

linuxprobe16
52分钟前
1
0
kubeadm部署kubernetes集群

一、环境要求 这里使用RHEL7.5 master、etcd:192.168.10.101,主机名:master node1:192.168.10.103,主机名:node1 node2:192.168.10.104,主机名:node2 所有机子能基于主机名通信,编辑...

人在艹木中
今天
7
0
Shell特殊符号总结以及cut,sort,wc,uniq,tee,tr,split命令

特殊符号总结一 * 任意个任意字符 ? 任意一个字符 # 注释字符 \ 脱义字符 | 管道符 # #号后的备注被忽略[root@centos01 ~]# ls a.txt # 备注 a.txt[root@centos01 ~]# a=1[root@centos01...

野雪球
今天
2
0
OSChina 周二乱弹 —— 程序员圣衣

Osc乱弹歌单(2018)请戳(这里) 【今日歌曲】 @达尔文:分享Skeeter Davis的单曲《The End of the World》 《The End of the World》- Skeeter Davis 手机党少年们想听歌,请使劲儿戳(这里...

小小编辑
今天
17
0
[ python import module ] 导入模块

import moudle_name ----> import module_name.py ---> import module_name.py文件路径 -----> sys.path (这里进行查找文件) # from app.web import Personimport app.web.Person as Pe......

_______-
昨天
5
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部