如何保持sysout和syserr流不混合?

时间:2010-11-23 11:52:31

标签: java error-handling stream

在我的代码库中是(非常简化的)以下内容:

public static void main (String[] args) {
   System.out.println("Starting application");
   try {
      System.out.println("About to validate");
      validate(args);
   catch (Exception e) {
      e.printStackTrace();
   }
}

public static void validate(String[] args) {
   System.out.println("Your first arg is " + args[0]);
   if (someProblemWith(args)) {
      System.out.println("Your args are wrong.  It should be: ...");
      throw new BadArgsException(e);
   }
}

哪个工作正常。请注意,上面的示例代码是设计的,只是为了在异常和堆栈跟踪打印之前显示多个日志语句。这通常意味着我的上一个日志记录语句在堆栈跟踪输出的中间丢失。是否有一种优雅的方式要求e.printStackTrace()语句等到System.out完成其工作?我基本上在寻找堆栈跟踪是发生错误时打印的最后一件事。以下是我的程序的示例输出:

 java.lang.Throwable
 ....
 at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
 at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
 at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
 Your args are wrong.  It should be: ...
 at java.lang.reflect.Method.invoke(Method.java:597)
 at org.eclipse.jdt.internal.jarinjarloader.JarRsrcLoader.main(JarRsrcLoader.java:56)

2 个答案:

答案 0 :(得分:8)

您看到在System.out.println()语句之间打印堆栈跟踪的原因是因为System.out被缓冲,而System.err(由堆栈跟踪使用)是无缓冲的。

如果您希望文本按照发生事件的确切顺序显示,则需要“取消缓冲”System.out。最简单的方法是在System.err处使用System.out而不是System.out.flush()

否则,在catch子句中发生堆栈跟踪之前调用Logger

选项2:使用.toString()类。

选项3:实现自己的“缓冲区”。换句话说,首先将所有内容写入您自己的缓冲区,包括堆栈跟踪(使用catch或您希望的话),然后在System.out刷新您自己的缓冲区。 (这有点多余,因为无论如何你只能刷新Logger

- == -

FROM COMMENT

不确定。 Logger类可用于创建更强大和详细的日志记录体验。这通常是在应用程序中完成的操作。 Logger类的一个实例从.log()类中获取(它是一个单例),将参数作为将使用的类。然后使用Logger方法将消息记录到它。关于DEBUG类的好处是你可以在它上面设置级别(例如WARN2010-11-23 14:45:32,032 DEBUG [MyClass] Your message ...),然后你就可以只过滤/显示你想要的内容。然后,“log”消息以统一的方式显示在控制台中,通常格式为:

log4j

以上格式来自Logger,但您可以使用标准Java {{1}}。输出应该类似,可能会少一些。但我确信它可以配置。

答案 1 :(得分:1)

致电e.printStackTrace(System.out);。或者,如果您只需要进行调试,可以将进程的输出和错误从命令行中分离出来:.... 1>output.log 2>error.log