stacktrace - java stack trace to stringbuilder




Wie kann ich eine Stapelverfolgung in eine Zeichenfolge konvertieren? (18)

Kotlin

Durch das Erweitern der Klasse Throwable erhalten Sie die String-Eigenschaft error.stackTraceString :

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

Was ist der einfachste Weg, um das Ergebnis von Throwable.getStackTrace() in eine Zeichenkette umzuwandeln, die den StackTrace darstellt?



Alte Frage, aber ich möchte nur den speziellen Fall hinzufügen, in dem Sie nicht den ganzen Stapel drucken wollen , indem Sie einige Teile entfernen, an denen Sie eigentlich nicht interessiert sind, ausgenommen bestimmte Klassen oder Pakete.

PrintWriter anstelle eines PrintWriter einen 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);

Wo die SelectivePrintWriter Klasse gegeben ist durch:

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);
        }
    }
}

Bitte beachten Sie, dass diese Klasse leicht angepasst werden kann, um Regex, contains oder andere Kriterien herauszufiltern. Beachten Sie auch, dass es von Throwable Implementierungsdetails abhängt (nicht wahrscheinlich, aber immer noch).


Code von 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();
}

Der Unterschied zu den anderen Antworten besteht darin, dass autoFlush für den PrintWriter .


Das sollte funktionieren:

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

Die Lösung besteht darin, StackTrace von Array in String- Datentyp zu konvertieren . Siehe das folgende Beispiel:

import java.util.Arrays;

try{

}catch(Exception ex){
    String stack = Arrays.toString(ex.getStackTrace());
    System.out.println("stack "+ stack);
}

Für mich war der sauberste und einfachste Weg:

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

Hier ist eine Version, die direkt in Code kopiert werden kann:

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());

Oder in einem Catch-Block

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

Mein oneliner, um Stack-Trace in den eingeschlossenen mehrzeiligen String zu konvertieren:

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

Einfach an den Logger übergeben "wie es ist".


Mit dem folgenden Code können Sie den gesamten StackTrace mit einem String Format abrufen, ohne APIs wie log4J oder sogar java.util.Logger :

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.
}

Ohne java.io.* kann das so gemacht werden.

String trace = e.toString() + "\n";                     

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

Und dann hält die trace Variable Ihre Stack-Trace. Ausgabe enthält auch die ursprüngliche Ursache, die Ausgabe ist identisch mit printStackTrace()

Beispiel, printStackTrace() ergibt:

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)

Die trace Zeichenfolge wird gespeichert, wenn sie in stdout gedruckt wird

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)

Stack-Trace auf String drucken

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 ist nützlich, wenn Sie den aktuellen Thread-Stack-Trace drucken möchten, ohne eine Instanz von Throwable zu erstellen. Throwable jedoch, dass das Erstellen eines neuen Throwable und das Throwable Stack-Trace von dort schneller und günstiger ist als der Aufruf von Thread.getStackTrace .


Verwenden Sie exp.printStackTrace() zum Anzeigen des Stacks Ihrer Exception.

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

WARNUNG: Enthält keine Ursache (was normalerweise das nützliche Bit ist!)

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

Wenn Sie für Android entwickeln, ist es ein viel einfacherer Weg, dies zu verwenden:

import android.util.Log;

String stackTrace = Log.getStackTraceString(exception); 

Das Format ist dasselbe wie getStackTrace, z

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)

Wenn Sie keine externe Bibliothek verwenden möchten und nicht für Android entwickeln , können Sie eine "Erweiterungsmethode" wie diese erstellen:

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

Arrays.toString(thrown.getStackTrace())

Ist der einfachste Weg, das Ergebnis in String zu konvertieren, verwende ich dies in meinem Programm, um den Stack-Trace zu drucken

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

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




tostring