How can I convert a stack trace to a string?

前端 未结 30 1168
再見小時候
再見小時候 2020-11-22 14:51

What is the easiest way to convert the result of Throwable.getStackTrace() to a string that depicts the stacktrace?

相关标签:
30条回答
  • 2020-11-22 15:00

    Without java.io.* it can be done like this.

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

    And then the trace variable holds your stack trace. Output also holds the initial cause, the output is identical to printStackTrace()

    Example, printStackTrace() yields:

    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)
    

    The trace String holds, when printed to 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)
    
    0 讨论(0)
  • 2020-11-22 15:00

    Scala version

    def stackTraceToString(e: Exception): String = {
      import java.io.PrintWriter
      val sw = new StringWriter()
      e.printStackTrace(new PrintWriter(sw))
      sw.toString
    }
    
    0 讨论(0)
  • 2020-11-22 15:02
    Arrays.toString(thrown.getStackTrace())
    

    Is the easiest way to convert the result into String I am using this in my program to print the stack trace

    LOGGER.log(Level.SEVERE, "Query Builder Issue Stack Trace : {0} ,Message : {1} objid {2}", new Object[]{Arrays.toString(e.getStackTrace()), e.getMessage(),objId});
    
    0 讨论(0)
  • 2020-11-22 15:03

    The clever sniping in the first set of comments was very amusing, but it really depends on what you are trying to do. If you don't already have the correct library, then 3 lines of code (as in D. Wroblewski's answer) is perfect. OTOH, if you already have the apache.commons library (as most large projects will), then Amar's answer is shorter. OK, it might take you ten minutes to get the library and install it correctly (less than one if you know what you're doing). But the clock is ticking, so you may not have the time to spare. Jarek Przygódzki had an interesting caveat--"If you don't need nested exceptions".

    But what if I do need the full stack traces, nested and all? In that case, the secret is to use apache.common's getFullStackTrace (see http://commons.apache.org/proper/commons-lang/javadocs/api-2.6/org/apache/commons/lang/exception/ExceptionUtils.html#getFullStackTrace%28java.lang.Throwable%29)

    It saved my bacon. Thanks, Amar, for the hint!

    0 讨论(0)
  • 2020-11-22 15:04

    I wrote a few methods for this a while ago, so I figured why not throw my two cents at this.

    /** @param stackTraceElements The elements to convert
     * @return The resulting string */
    public static final String stackTraceElementsToStr(StackTraceElement[] stackTraceElements) {
        return stackTraceElementsToStr(stackTraceElements, "\n");
    }
    
    /** @param stackTraceElements The elements to convert
     * @param lineSeparator The line separator to use
     * @return The resulting string */
    public static final String stackTraceElementsToStr(StackTraceElement[] stackTraceElements, String lineSeparator) {
        return stackTraceElementsToStr(stackTraceElements, lineSeparator, "");
    }
    
    /** @param stackTraceElements The elements to convert
     * @param lineSeparator The line separator to use
     * @param padding The string to be used at the start of each line
     * @return The resulting string */
    public static final String stackTraceElementsToStr(StackTraceElement[] stackTraceElements, String lineSeparator, String padding) {
        String str = "";
        if(stackTraceElements != null) {
            for(StackTraceElement stackTrace : stackTraceElements) {
                str += padding + (!stackTrace.toString().startsWith("Caused By") ? "\tat " : "") + stackTrace.toString() + lineSeparator;
            }
        }
        return str;
    }
    
    /** @param stackTraceElements The elements to convert
     * @return The resulting string */
    public static final String stackTraceCausedByElementsOnlyToStr(StackTraceElement[] stackTraceElements) {
        return stackTraceCausedByElementsOnlyToStr(stackTraceElements, "\n");
    }
    
    /** @param stackTraceElements The elements to convert
     * @param lineSeparator The line separator to use
     * @return The resulting string */
    public static final String stackTraceCausedByElementsOnlyToStr(StackTraceElement[] stackTraceElements, String lineSeparator) {
        return stackTraceCausedByElementsOnlyToStr(stackTraceElements, lineSeparator, "");
    }
    
    /** @param stackTraceElements The elements to convert
     * @param lineSeparator The line separator to use
     * @param padding The string to be used at the start of each line
     * @return The resulting string */
    public static final String stackTraceCausedByElementsOnlyToStr(StackTraceElement[] stackTraceElements, String lineSeparator, String padding) {
        String str = "";
        if(stackTraceElements != null) {
            for(StackTraceElement stackTrace : stackTraceElements) {
                str += (!stackTrace.toString().startsWith("Caused By") ? "" : padding + stackTrace.toString() + lineSeparator);
            }
        }
        return str;
    }
    
    /** @param e The {@link Throwable} to convert
     * @return The resulting String */
    public static final String throwableToStrNoStackTraces(Throwable e) {
        return throwableToStrNoStackTraces(e, "\n");
    }
    
    /** @param e The {@link Throwable} to convert
     * @param lineSeparator The line separator to use
     * @return The resulting String */
    public static final String throwableToStrNoStackTraces(Throwable e, String lineSeparator) {
        return throwableToStrNoStackTraces(e, lineSeparator, "");
    }
    
    /** @param e The {@link Throwable} to convert
     * @param lineSeparator The line separator to use
     * @param padding The string to be used at the start of each line
     * @return The resulting String */
    public static final String throwableToStrNoStackTraces(Throwable e, String lineSeparator, String padding) {
        if(e == null) {
            return "null";
        }
        String str = e.getClass().getName() + ": ";
        if((e.getMessage() != null) && !e.getMessage().isEmpty()) {
            str += e.getMessage() + lineSeparator;
        } else {
            str += lineSeparator;
        }
        str += padding + stackTraceCausedByElementsOnlyToStr(e.getStackTrace(), lineSeparator, padding);
        for(Throwable suppressed : e.getSuppressed()) {
            str += padding + throwableToStrNoStackTraces(suppressed, lineSeparator, padding + "\t");
        }
        Throwable cause = e.getCause();
        while(cause != null) {
            str += padding + "Caused by:" + lineSeparator + throwableToStrNoStackTraces(e.getCause(), lineSeparator, padding);
            cause = cause.getCause();
        }
        return str;
    }
    
    /** @param e The {@link Throwable} to convert
     * @return The resulting String */
    public static final String throwableToStr(Throwable e) {
        return throwableToStr(e, "\n");
    }
    
    /** @param e The {@link Throwable} to convert
     * @param lineSeparator The line separator to use
     * @return The resulting String */
    public static final String throwableToStr(Throwable e, String lineSeparator) {
        return throwableToStr(e, lineSeparator, "");
    }
    
    /** @param e The {@link Throwable} to convert
     * @param lineSeparator The line separator to use
     * @param padding The string to be used at the start of each line
     * @return The resulting String */
    public static final String throwableToStr(Throwable e, String lineSeparator, String padding) {
        if(e == null) {
            return "null";
        }
        String str = padding + e.getClass().getName() + ": ";
        if((e.getMessage() != null) && !e.getMessage().isEmpty()) {
            str += e.getMessage() + lineSeparator;
        } else {
            str += lineSeparator;
        }
        str += padding + stackTraceElementsToStr(e.getStackTrace(), lineSeparator, padding);
        for(Throwable suppressed : e.getSuppressed()) {
            str += padding + "Suppressed: " + throwableToStr(suppressed, lineSeparator, padding + "\t");
        }
        Throwable cause = e.getCause();
        while(cause != null) {
            str += padding + "Caused by:" + lineSeparator + throwableToStr(e.getCause(), lineSeparator, padding);
            cause = cause.getCause();
        }
        return str;
    }
    

    Example:

    try(InputStream in = new FileInputStream(file)) {
        ...
    } catch(IOException e) {
        String exceptionToString = throwableToStr(e);
        someLoggingUtility.println(exceptionToString);
        ...
    }
    

    Prints:

    java.io.FileNotFoundException: C:\test.txt (The system cannot find the file specified)
        at java.io.FileInputStream.open0(Native Method)
        at java.io.FileInputStream.open(Unknown Source)
        at java.io.FileInputStream.<init>(Unknown Source)
        at com.gmail.br45entei.Example.main(Example.java:32)
    
    0 讨论(0)
  • 2020-11-22 15:05

    if you are using Java 8, try this

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

    you can find the code for getStackTrace() function provided by Throwable.java as :

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

    and for StackTraceElement, it provides toString() as follows:

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

    So just join the StackTraceElement with "\n".

    0 讨论(0)
提交回复
热议问题