Posts Java IO - ByteArray流的重用
Post
Cancel

Java IO - ByteArray流的重用

ByteArrayInputSteam类将内存中的字节数组作为数据源,利用这个特性,可以通过ByteArrayInputSteam重用一些需要特殊处理、或者重复使用的字节数组或大字符串,比如XML格式的内容。

一个有用的场景是对于异常的特殊处理。一般而言,我们简单地通过 Exception.printStackTrace()方法直接输出异常栈到标准输出stdout。

异常的一般性处理

1
2
3
4
5
try {
  int x = 1 / 0;  // <--- 
} catch (Exception e) {
  e.printStackTrace();
}

这个简单例子演示被除数为0的异常输出。下面这个输出比较特殊,因为例子代码是在intellij编辑器中执行,所以栈中有调用者intellij的信息。

1
2
3
4
5
6
7
java.lang.ArithmeticException: / by zero
	at cn.xwiz.lab.io.ByteArrayClient.main(ByteArrayClient.java:11)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at com.intellij.rt.execution.application.AppMain.main(AppMain.java:120)

上面输出7行数据,大量的异常输出会导致日志文件越来越庞大,一个有效的做法是压缩异常的输出量,比如只输出异常栈的前面若干行。

Throwable特殊处理

可以将Throwable对象通过PrintStream或者PrintWriter写入到ByteArrayOutputStream中。ByteArrayOutputStream内部保存了一个字节数组,可以作为ByteArrayInputStream的数据源。 接下来通过ByteArrayInputStream作为BufferedReader的输入流,处理每一行数据。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
public static void main(String args[]) {
	try {
	  int x = 1 / 0;
	} catch (Exception e) {
	  //e.printStackTrace();
	  printMyTrace(e);
	}
}

public static void printMyTrace(Throwable t) {
	final int line = 3;
	try {
	  ByteArrayOutputStream bos = new ByteArrayOutputStream();
	  PrintStream ps = new PrintStream(bos);
	  t.printStackTrace(ps);

	  ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
	  BufferedReader br = new BufferedReader(new InputStreamReader(bis));
	  for (int i = 0; i < line; i++) {
		String s = br.readLine().toString();
		System.err.println(s);
	  }
	} catch (Exception e) {
	  // do nothing
	}
}

这里涉及到ByteArrayInputStream的重用性,虽然例子中只用了一次并作为stderr输出,但在方法体printMyTrace内可以重用ByteArrayInputStream的实例bis,做其他的处理,比如全部写入一个邮件内发送,或写入stdout,或使用另外一种形式的过滤,比如过滤每一行只输出含有cn.xwiz包的信息。

上面的代码输出结果就比较简洁。

1
2
3
java.lang.ArithmeticException: / by zero
	at cn.xwiz.lab.io.ByteArrayClient.main(ByteArrayClient.java:11)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
This post is licensed under CC BY 4.0 by the author.