如何将堆栈跟踪转换为字符串?

Throwable.getStackTrace()的结果转换为描述堆栈跟踪的字符串的最简单方法是什么?

可以使用下面的方法将Exception堆栈跟踪转换为String 。 这个类在Apache commons-lang中是可用的, 这是许多流行开源的最常见的依赖库

org.apache.commons.lang.exception.ExceptionUtils.getStackTrace(Throwable)

使用Throwable.printStackTrace(PrintWriter pw)将堆栈跟踪发送到适当的作者。

 import java.io.StringWriter; import java.io.PrintWriter; // ... StringWriter sw = new StringWriter(); PrintWriter pw = new PrintWriter(sw); e.printStackTrace(pw); String sStackTrace = sw.toString(); // stack trace as a string System.out.println(sStackTrace); 

这应该工作:

 StringWriter sw = new StringWriter(); e.printStackTrace(new PrintWriter(sw)); String exceptionAsString = sw.toString(); 

如果您正在为Android开发,更简单的方法是使用这个:

 import android.util.Log; String stackTrace = Log.getStackTraceString(exception); 

格式与getStacktrace相同,例如

 09-24 16:09:07.042: I/System.out(4844): java.lang.NullPointerException 09-24 16:09:07.042: I/System.out(4844): at com.temp.ttscancel.MainActivity.onCreate(MainActivity.java:43) 09-24 16:09:07.042: I/System.out(4844): at android.app.Activity.performCreate(Activity.java:5248) 09-24 16:09:07.043: I/System.out(4844): at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1110) 09-24 16:09:07.043: I/System.out(4844): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2162) 09-24 16:09:07.043: I/System.out(4844): at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2257) 09-24 16:09:07.043: I/System.out(4844): at android.app.ActivityThread.access$800(ActivityThread.java:139) 09-24 16:09:07.043: I/System.out(4844): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1210) 09-24 16:09:07.043: I/System.out(4844): at android.os.Handler.dispatchMessage(Handler.java:102) 09-24 16:09:07.043: I/System.out(4844): at android.os.Looper.loop(Looper.java:136) 09-24 16:09:07.044: I/System.out(4844): at android.app.ActivityThread.main(ActivityThread.java:5097) 09-24 16:09:07.044: I/System.out(4844): at java.lang.reflect.Method.invokeNative(Native Method) 09-24 16:09:07.044: I/System.out(4844): at java.lang.reflect.Method.invoke(Method.java:515) 09-24 16:09:07.044: I/System.out(4844): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:785) 09-24 16:09:07.044: I/System.out(4844): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:601) 

警告:不包括原因(这通常是有用的位!)

 public String stackTraceToString(Throwable e) { StringBuilder sb = new StringBuilder(); for (StackTraceElement element : e.getStackTrace()) { sb.append(element.toString()); sb.append("\n"); } return sb.toString(); } 

番石榴的Throwables

如果您有实际的Throwable实例,则Google Guava将提供Throwables.getStackTraceAsString()

例:

 String s = Throwables.getStackTraceAsString ( myException ) ; 

对我来说,最简单最简单的方法是:

 import java.util.Arrays; Arrays.toString(e.getStackTrace()); 

下面的代码允许你使用String格式获取整个stackTrace,而不需要使用像log4J甚至java.util.Logger这样的API:

 catch (Exception e) { StackTraceElement[] stack = e.getStackTrace(); String exception = ""; for (StackTraceElement s : stack) { exception = exception + s.toString() + "\n\t\t"; } System.out.println(exception); // then you can send the exception string to a external file. } 

受@Brian Agnew启发:

 public static String getStackTrace(Throwable t) { StringWriter sw = new StringWriter(); t.printStackTrace(new PrintWriter(sw)); return sw.toString(); } 

这是一个可直接复制到代码中的版本:

 import java.io.StringWriter; import java.io.PrintWriter; //Two lines of code to get the exception into a StringWriter StringWriter sw = new StringWriter(); new Throwable().printStackTrace(new PrintWriter(sw)); //And to actually print it logger.info("Current stack trace is:\n" + sw.toString()); 

或者,在一个catch块

 } catch (Throwable t) { StringWriter sw = new StringWriter(); t.printStackTrace(new PrintWriter(sw)); logger.info("Current stack trace is:\n" + sw.toString()); } 

将堆栈跟踪打印到字符串

 import java.io.PrintWriter; import java.io.StringWriter; public class StackTraceUtils { public static String stackTraceToString(StackTraceElement[] stackTrace) { StringWriter sw = new StringWriter(); printStackTrace(stackTrace, new PrintWriter(sw)); return sw.toString(); } public static void printStackTrace(StackTraceElement[] stackTrace, PrintWriter pw) { for(StackTraceElement stackTraceEl : stackTrace) { pw.println(stackTraceEl); } } } 

当你想打印当前线程堆栈跟踪而不创建Throwable实例时,这很有用 – 但是请注意,从那里创建新的Throwable并获取堆栈跟踪实际上比调用Thread.getStackTrace更快,更便宜。

没有java.io.*可以这样做。

 String trace = e.toString() + "\n"; for (StackTraceElement e1 : e.getStackTrace()) { trace += "\t at " + e1.toString() + "\n"; } 

然后trace变量保存你的堆栈跟踪。 输出也包含最初的原因,输出与printStackTrace()相同

例如, printStackTrace()产生:

 java.io.FileNotFoundException: / (Is a directory) at java.io.FileOutputStream.open0(Native Method) at java.io.FileOutputStream.open(FileOutputStream.java:270) at java.io.FileOutputStream.<init>(FileOutputStream.java:213) at java.io.FileOutputStream.<init>(FileOutputStream.java:101) at Test.main(Test.java:9) 

trace字符串保持,当打印到stdout

 java.io.FileNotFoundException: / (Is a directory) at java.io.FileOutputStream.open0(Native Method) at java.io.FileOutputStream.open(FileOutputStream.java:270) at java.io.FileOutputStream.<init>(FileOutputStream.java:213) at java.io.FileOutputStream.<init>(FileOutputStream.java:101) at Test.main(Test.java:9) 

来自Apache Commons Lang 3.4的代码( JavaDoc ):

 public static String getStackTrace(final Throwable throwable) { final StringWriter sw = new StringWriter(); final PrintWriter pw = new PrintWriter(sw, true); throwable.printStackTrace(pw); return sw.getBuffer().toString(); } 

与其他答案的区别是它使用 PrintWriter上的autoFlush

科特林

扩展Throwable类会给你String属性error.stackTraceString

 val Throwable.stackTraceString: String get() { val sw = StringWriter() val pw = PrintWriter(sw) this.printStackTrace(pw) return sw.toString() } 

第一组评论中的聪明狙击非常有趣,但这取决于你想做什么。 如果你还没有正确的库,那么3行代码(如D. Wroblewski的答案)是完美的。 OTOH,如果你已经有了apache.commons库(就像大多数大项目一样),那么Amar的答案就更短了。 好吧,可能需要10分钟才能获得库并正确安装(如果您知道自己在做什么,可以少于1分钟)。 但时钟正在滴答,所以你可能没有时间空闲。 JarekPrzygódzki有一个有趣的警告 – “如果你不需要嵌套异常”。

但是,如果我确实需要完整的堆栈跟踪,嵌套和所有? 在这种情况下,秘诀是使用apache.common的getFullStackTrace(请参阅http://commons.apache.org/proper/commons-lang/javadocs/api-2.6/org/apache/commons/lang/exception/ExceptionUtils.html #getFullStackTrace%28java.lang.Throwable%29 )

它救了我的培根。 谢谢,阿马尔,提示!

 private String getCurrentStackTraceString() { StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace(); return Arrays.stream(stackTrace).map(StackTraceElement::toString) .collect(Collectors.joining("\n")); } 

嘎拉答案的扩大也将包括例外的原因:

 private String extrapolateStackTrace(Exception ex) { Throwable e = ex; String trace = e.toString() + "\n"; for (StackTraceElement e1 : e.getStackTrace()) { trace += "\t at " + e1.toString() + "\n"; } while (e.getCause() != null) { e = e.getCause(); trace += "Cause by: " + e.toString() + "\n"; for (StackTraceElement e1 : e.getStackTrace()) { trace += "\t at " + e1.toString() + "\n"; } } return trace; } 

如果您不想使用外部库,而您又不是为Android开发的 ,则可以创建如下所示的“扩展”方法 :

 public static String getStackTraceString(Throwable e) { return getStackTraceString(e, ""); } private static String getStackTraceString(Throwable e, String indent) { StringBuilder sb = new StringBuilder(); sb.append(e.toString()); sb.append("\n"); StackTraceElement[] stack = e.getStackTrace(); if (stack != null) { for (StackTraceElement stackTraceElement : stack) { sb.append(indent); sb.append("\tat "); sb.append(stackTraceElement.toString()); sb.append("\n"); } } Throwable[] suppressedExceptions = e.getSuppressed(); // Print suppressed exceptions indented one level deeper. if (suppressedExceptions != null) { for (Throwable throwable : suppressedExceptions) { sb.append(indent); sb.append("\tSuppressed: "); sb.append(getStackTraceString(throwable, indent + "\t")); } } Throwable cause = e.getCause(); if (cause != null) { sb.append(indent); sb.append("Caused by: "); sb.append(getStackTraceString(cause, indent)); } return sb.toString(); } 

老问题,但我只想添加特殊情况,你不想打印所有的堆栈 ,删除一些你不是真正感兴趣的部分,不包括某些类或包。

而不是PrintWriter使用SelectivePrintWriter

 // This filters out this package and up. String packageNameToFilter = "org.springframework"; StringWriter sw = new StringWriter(); PrintWriter pw = new SelectivePrintWriter(sw, packageNameToFilter); e.printStackTrace(pw); String sStackTrace = sw.toString(); System.out.println(sStackTrace); 

SelectivePrintWriter类由以下项目给出:

 public class SelectivePrintWriter extends PrintWriter { private boolean on = true; private static final String AT = "\tat"; private String internal; public SelectivePrintWriter(Writer out, String packageOrClassName) { super(out); internal = "\tat " + packageOrClassName; } public void println(Object obj) { if (obj instanceof String) { String txt = (String) obj; if (!txt.startsWith(AT)) on = true; else if (txt.startsWith(internal)) on = false; if (on) super.println(txt); } else { super.println(obj); } } } 

请注意,这个类可能很容易适应通过正则表达式, contains或其他标准过滤掉。 还要注意它取决于Throwable实现细节(不太可能改变,但仍然)。