繁体   English   中英

即使在设置 System.setErr() 后也无法使用自定义 PrintStream 进行打印的错误

[英]Errors not printing using custom PrintStream even after setting System.setErr()

基本上,我想让控制台做两件事:

  1. 我希望控制台为错误代码和一般信息消息着色(其中错误为红色,其他所有错误为绿色)。
  2. 我想将所有控制台消息保存到日志文件中。

所以,我创建了一个看起来像这样的打印 stream:

public static class GeneralStream extends PrintStream {

    public GeneralStream(OutputStream out) {
        super(out);
    }

    @Override
    public void println(String string) {
        String time = DateTimeFormatter.ofPattern("HH:mm:ss").format(LocalDateTime.now());

        String output = "["+time+"] ["+type.n()+"] "+string;
        Logs.logToFile(output);
        
        String coloredOutput = ANSI_RESET+ANSI_WHITE+"["+ANSI_CYAN+time+ANSI_WHITE+"] "+
                ANSI_WHITE+"["+ANSI_RESET+type.c()+type.n()+ANSI_WHITE+"] "+type.c()+string+ANSI_RESET;
        super.println(coloredOutput);
    }
}

伟大的。 然后我在我的程序开始时将此打印 stream 设置为默认 PrintStream 使用:

// Set console output settings
    System.setOut(new Console.GeneralStream(System.out));
    System.setErr(new Console.GeneraStream(System.err));

惊人的。 最后,在执行 System.out.println("Hello World") 时,我得到了预期的结果。 我的消息是彩色的。 它们被记录到一个文件中。 伟大的。 事实上,即使我执行 System.err,println("Error."),我仍然会得到预期的结果。 但是,“自动”异常不会通过我设置的 System.err 打印

这是一个例子:

// Set console output settings
    System.setOut(new Console.GeneralStream(System.out));
    System.setErr(new Console.ErrorStream(System.err));

    System.out.println("Hello world!");
    System.err.println("Printing an error!");

    // Real exception (NPE)
    Integer nullInteger = null;
    System.out.println(nullInteger.toString()); // won't print and will produce a NullPointException

结果如下:如您所见,我的 System.out 和 System.err 打印正常,但一旦出现真正的异常,它就会定期打印。

所以我的问题是如何为这样的错误设置自定义 PrintStream 以便将它们记录到文件中(最好遵循我的自定义消息格式)。

如果您深入研究Throwable class 如何打印堆栈跟踪,您会看到它使用println(Object)方法,因此您需要将此方法添加到您的自定义 ErrorStream class 中:

@Override
public void println(Object object) {
    println(String.valueOf(object));
}

即使这样,您也可能希望更改“未捕获的异常处理程序”以更改它记录异常的方式。 似乎默认处理程序首先调用System.err.printException in thread "{ThreadName}"然后是Throwable.printStackTrace ,因此您最终会在消息中间获得时间戳和其他内容。 例如:

    Thread.setDefaultUncaughtExceptionHandler((thread, throwable) -> {
        System.err.println("Uncaught exception in thread " + thread.getName());
        throwable.printStackTrace(System.err);
    });

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM