首页 文章

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

提问于
浏览
1275

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

28 回答

  • 18

    灵感来自@Brian Agnew:

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

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

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

  • 106

    我的oneliner将堆栈跟踪转换为包含的多行字符串:

    Stream.of(e.getStackTrace()).map((a) -> a.toString()).collect(Collectors.joining("\n", "[", "]"))
    

    很容易“按原样”传递给 Logger .

  • 9

    如果您正在为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):在android.app.Activity.performCreate(Activity.java:5248)
    09-24 16:09:07.043:I / System.out(4844):在android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1110)
    09-24 16:09:07.043:I / System.out(4844):在android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2162)
    09-24 16:09:07.043:I / System.out(4844):在android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2257)
    09-24 16:09:07.043:I / System.out(4844):在android.app.ActivityThread.access $ 800(ActivityThread.java:139)
    09-24 16:09:07.043:I / System.out(4844):在android.app.ActivityThread $ H.handleMessage(ActivityThread.java:1210)
    09-24 16:09:07.043:I / System.out(4844):在android.os.Handler.dispatchMessage(Handler.java:102)
    09-24 16:09:07.043:I / System.out(4844):在android.os.Looper.loop(Looper.java:136)
    09-24 16:09:07.044:I / System.out(4844):在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)

  • 108

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

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

    以下代码允许您使用 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.
    }
    
  • 9

    科特林

    扩展Throwable类将为您提供String属性 error.stackTraceString

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

    Guava 的Throwables类

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

    例:

    String s = Throwables.getStackTraceAsString ( myException ) ;
    
  • 889

    使用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);
    
  • 2

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

    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 (Throwable t) {
        StringWriter sw = new StringWriter();
        t.printStackTrace(new PrintWriter(sw));
        logger.info("Current stack trace is:\n" + sw.toString());
    }
    
  • 2

    这应该工作:

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

    对Gala的回答进行了扩展,其中还包括异常的原因:

    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;
    }
    
  • 10

    没有 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)
    
  • 4

    警告:这可能有点偏离主题,但是很好......;)

    我不知道原始海报的原因是首先想要将堆栈跟踪作为字符串 . 当堆栈跟踪应该在SLF4J / Logback LOG中结束时,但是没有或者应该抛出异常,这就是我所做的:

    public void remove(List<String> ids) {
        if(ids == null || ids.isEmpty()) {
            LOG.warn(
                "An empty list (or null) was passed to {}.remove(List). " +
                "Clearly, this call is unneccessary, the caller should " + 
                "avoid making it. A stacktrace follows.", 
                getClass().getName(),
                new Throwable ("Stacktrace")
            );
    
            return;
        }
    
        // actual work, remove stuff
    }
    

    我喜欢它,因为它不需要外部库(除了你的日志记录后端,当然,大多数时候它都将在适当的位置使用) .

  • 24
    Arrays.toString(thrown.getStackTrace())
    

    是将结果转换为String的最简单方法我在程序中使用它来打印堆栈跟踪

    LOGGER.log(Level.SEVERE, "Query Builder Issue Stack Trace : {0} ,Message : {1} objid {2}", new Object[]{Arrays.toString(e.getStackTrace()), e.getMessage(),objId});
    
  • 10

    第一组评论中的聪明狙击是非常有趣的,但这实际上取决于你想要做什么 . 如果你还没有正确的库,那么3行代码(如在D. Wroblewski的答案中)是完美的 . OTOH,如果你已经有了apache.commons库(就像大多数大型项目那样),那么Amar的答案就更短了 . 好的,你可能需要十分钟才能获得库并正确安装(如果你知道你在做什么的话,不到一个) . 但时间在流逝,所以你可能没有时间 . 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

    它救了我的培根 . 谢谢,阿玛,提示!

  • 0

    使用 exp.printStackTrace() 显示异常堆栈 .

    try {
       int zero = 1 - 1;
       int a = 1/zero;
    } catch (Exception e) {
        e.printStackTrace();
    }
    
  • 6

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

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

    老问题,但我想通过删除一些您实际上并不感兴趣的部分来添加特殊情况 don't want to print all the stack ,不包括某些类或包 .

    而不是 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);
            }
        }
    }
    

    请注意,此类可以很容易地通过Regex, contains 或其他标准进行过滤 . 另请注意,它取决于 Throwable 实现细节(不太可能改变,但仍然) .

  • 7

    如果您使用的是Java 8,请尝试此操作

    Arrays.stream(e.getStackTrace())
                    .map(s->s.toString())
                    .collect(Collectors.joining("\n"));
    

    你可以找到Throwable.java提供的getStackTrace()函数的代码:

    public StackTraceElement[] getStackTrace() {
        return getOurStackTrace().clone();
    }
    

    对于StackTraceElement,它将toString提供为:

    public String toString() {
        return getClassName() + "." + methodName +
            (isNativeMethod() ? "(Native Method)" :
             (fileName != null && lineNumber >= 0 ?
              "(" + fileName + ":" + lineNumber + ")" :
              (fileName != null ?  "("+fileName+")" : "(Unknown Source)")));
    }
    

    所以只需使用“\ n”加入StackTraceElement即可

  • 82

    如果你没有't want to use an external library and you'没有开发for Android,你可以像这样创建一个'extension' method

    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();
    }
    
  • 25

    将stacktrace打印到PrintStream,然后将其转换为String

    // ...
    
    catch (Exception e)
    {
        ByteArrayOutputStream out = new ByteArrayOutputStream(); 
        e.printStackTrace(new PrintStream(out));
        String str = new String(out.toByteArray());
    
        System.out.println(str);
    }
    
  • 1981

    代码来自 Apache Commons Lang 3.4JavaDoc):

    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 上的 it uses autoFlush .

  • 416
    private String getCurrentStackTraceString() {
        StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace();
        return Arrays.stream(stackTrace).map(StackTraceElement::toString)
                .collect(Collectors.joining("\n"));
    }
    
  • 3
    import java.io.PrintWriter;
    import java.io.StringWriter;
    
    public class PrintStackTrace {
    
        public static void main(String[] args) {
    
            try {
                int division = 0 / 0;
            } catch (ArithmeticException e) {
                StringWriter sw = new StringWriter();
                e.printStackTrace(new PrintWriter(sw));
                String exceptionAsString = sw.toString();
                System.out.println(exceptionAsString);
            }
        }
    }
    

    运行程序时,输出类似于:

    java.lang.ArithmeticException: / by zero
    at PrintStackTrace.main(PrintStackTrace.java:9)
    
  • 2

    解决方案是 to convert the stackTrace of array to string 数据类型 . 请参阅以下示例:

    import java.util.Arrays;
    
    try{
    
    }catch(Exception ex){
        String stack = Arrays.toString(ex.getStackTrace());
        System.out.println("stack "+ stack);
    }
    
  • -1

    几个选项

  • 4

    将堆栈跟踪打印到字符串

    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 更快,更便宜 .

相关问题