phi*_*294 7 java stdout exception throw stderr
我希望我的程序例外发送到以下每个,最好是同时发送:
我怎样才能做到这一点?
我的尝试:
System.setErr(PrintStream err)
将所有例外转发给新流.我不能说多个流.
打电话System.setErr(PrintStream err)
给人工书面OutputStream
:
"你可以编写自己的流类转发到多个流,并在该类的实例上调用System.setOut" - Jeffrey Bosboom
我找到了一种方法来做到这一点.但这非常讨厌.它"收集" PrintStream
's write
-bytes,将它们放入一个吹气(500毫秒超时),最后显示给用户(Proceed
):
/* ErrorOutput.java */
public static t_ErrBuffer t_activeErrBuffer = new t_ErrBuffer("");
public static void setStdErrToFile(final File file) {
ps = new PrintStream(fos) {
@Override
public void write(byte[] buf, int off, int len) {
byte[] bn = new byte[len];
for (int i = off, j = 0; i < (len + off); i++, j++) {
bn[j] = buf[i];
}
String msg = null;
try {
msg = new String(bn, "UTF-8");
} catch (UnsupportedEncodingException e1) {}
if (msg.matches("[\\w\\W]*[\\w]+[\\w\\W]*")) { // ^= contains at least one word character
if( ! t_activeErrBuffer.isAlive() ) {
t_activeErrBuffer = new t_ErrBuffer(msg);
t_activeErrBuffer.start();
} else {
t_activeErrBuffer.interrupt();
t_activeErrBuffer = new t_ErrBuffer(t_activeErrBuffer.getErrBuffer() + "\n" + msg); // ^= append to buffer and restart.
t_activeErrBuffer.start();
}
}
}
};
System.setErr(ps);
}
/* t_ErrBuffer.java */
public class t_ErrBuffer extends Thread {
private String errBuffer;
public t_ErrBuffer(String buffer) {
this.errBuffer = buffer;
}
protected class Proceed implements Runnable {
public String msg = null;
public Proceed(String msg) {
this.msg = msg;
}
@Override
public void run() {
// todo PRINT ERROR MESSAGE: DO THINGS WITH msg: console, gui, JOptionPane
}
}
@Override
public void run() {
try {
Thread.sleep(500); // collect error lines before output. Needed because PrintStream's "write"-method writes ErrorMessages in multiple pieces (lines)
// each time some new exception line comes in, the thread is stopped, buffer is being appended and thread new started
} catch (InterruptedException e) {
return; // stop
}
// after 500 ms of wait, no new error message line has come in. Print the message out:
Thread t_tmp = new Thread(new Proceed("\n" + this.errBuffer));
t_tmp.start();
return;
}
public String getErrBuffer() {
return this.errBuffer;
}
}
Run Code Online (Sandbox Code Playgroud)
这是我应该做的吗?
创建新的异常类,它为我做.可能会工作,但除此之外的其他例外(IO,FileNotFound,...)仍然会以旧的方式处理
而不是声明[method name] throws Exception
我可以将所有代码都包含在try/catch-blocks中,获取异常并将其转发给我的方法,如下所示:
/* AnyMethod.java */
// ...
try {
// ... do everything here
} catch (IOException | FileNotFoundException e) { // as many as you like
ErrorOutput.crash(e);
}
// ...
/* ErrorOutput.java */
public static void crash(Exception e) {
FileOutputStream fos_errOutput = new FileOutputStream(new File("ErrorOutput.txt"), true);
// 1st
if (!System.out.equals(fos_errOutput)) {
System.out.println(e.getMessage() + " :"); // to console or the preferred StdOut
e.printStackTrace();
}
// 2nd
JOptionPane.showMessageDialog(Gui.frame, "THE PROGRAM HAS CRASHED!" + "\n\n" + e.getMessage() + "\n\nFor a more detailed report, see ErrorLog.txt"); // gui output
// 3rd
PrintStream ps = new PrintStream(fos_errOutput);
ps.print(new Date().toString() + ":"); // write to file
e.printStackTrace(ps);
ps.close();
// 4th
System.exit(0); // this could also be "throw new Exception" etc., but I don't know why one should do that.
}
Run Code Online (Sandbox Code Playgroud)
这可能也会奏效,但我必须把所有东西放到try/catch-blocks中.这根本不是好的编程风格.
使用记录器:
"使用log4j并设置一个方法来写入GUI并记录到stdout和文件" - Scary Wombat
记录器只能帮助我将异常打印到所需的流中,但它们无法帮助我捕获它们,对吧?
但你真的应该使用一个日志包 - 甚至java.util.logging可以做你需要的 - Jeffrey Bosboom
我必须告诉我的日志包在哪里以及记录什么.但这正是我所寻找的.
我现在可以像user3159253建议的那样,Thread.UncaughtExceptionHandler
专门用于捕获未处理的异常.
以我希望的方式处理所有抛出异常的正确方法是什么?除了Thread.UncaughtExceptionHandler
和System.setErr()
(见上文)我还需要考虑什么?
首先,您需要获取从线程中/内部抛出的所有异常实例(可能是try/catch或Thread.UncoughtExceptionHandler
or ThreadPoolExecutor.afterExecute(Runnable r, Throwable t)
).
然后,一旦有了异常实例,您只需使用log4j进行日志记录,但可以配置Log4j appender将异常消息发送到多个目标.您可以根据需要使用文件,控制台,JDBC,JMS等类型的appender.最好用Async appender包装它们.
请参阅 - https://logging.apache.org/log4j/2.x/manual/appenders.html
关于将异常消息推送到GUI,它可以通过各种方式实现,具体取决于您在应用程序中使用的技术堆栈.在我们的应用程序中,我们将消息事件(仅限关键事件)存储在数据库中,然后由服务器的事件监视线程选择,然后使用http://cometd.org/documentation/cometd-将其推送回GUI(JQuery,JavaScript).java.
归档时间: |
|
查看次数: |
259 次 |
最近记录: |