Wie konvertiert man am einfachsten das Ergebnis von Throwable.getStackTrace()
zu einer Zeichenkette, die den Stacktrace darstellt?
Und was ist ExceptionUtils?
Wie konvertiert man am einfachsten das Ergebnis von Throwable.getStackTrace()
zu einer Zeichenkette, die den Stacktrace darstellt?
Warnung: Dies könnte ein wenig vom Thema abweichen, aber na ja... ;)
Ich weiß nicht, was die ursprünglichen Poster Grund war, weil er den Stack-Trace überhaupt erst als String haben wollte. Wenn der Stacktrace in einem SLF4J/Logback LOG landen sollte, aber keine Exception geworfen wurde oder werden sollte, mache ich folgendes:
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
}
Ich mag es, weil es keine externe Bibliothek benötigt (abgesehen von Ihrem Logging-Backend, das natürlich die meiste Zeit sowieso vorhanden sein wird).
Wenige Optionen
StringWriter sw = new StringWriter(); e.printStackTrace(new PrintWriter(sw)); String exceptionAsString = sw.toString();
Verwendung der Google Guava Lib String stackTrace = Throwables.getStackTraceAsString ( myException ) ;
org.apache.commons.lang.exception.ExceptionUtils.getStackTrace(Throwable)
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);
}
}
}
Wenn Sie das Programm ausführen, wird die Ausgabe in etwa so aussehen:
java.lang.ArithmeticException: / by zero
at PrintStackTrace.main(PrintStackTrace.java:9)
Ich habe vor einiger Zeit ein paar Methoden dafür geschrieben, also dachte ich mir, warum nicht meinen Senf dazu geben.
/** @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;
}
Beispiel:
try(InputStream in = new FileInputStream(file)) {
...
} catch(IOException e) {
String exceptionToString = throwableToStr(e);
someLoggingUtility.println(exceptionToString);
...
}
Drucke:
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)
CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.
8 Stimmen
Die Antwort von jqno verwendet nämlich die Methode Throwable.getStackTrace(), die Sie in Ihrer Frage angegeben haben, während Brian dies nicht tut. Er verwendet stattdessen Throwable.printStackTrace().
10 Stimmen
So gut wie jedes Java-Projekt sollte Apache commons-lang enthalten. Es enthält viele bequeme Methoden, die extrem häufige Entwicklungsanforderungen implementieren.
20 Stimmen
@StijndeWitt Diese drei Codezeilen müssen mit ziemlicher Sicherheit von der Stelle, an der Sie sie aufgerufen haben, ausgeklammert werden. Da Sie nicht wissen, wohin sie gehören, landen sie in Ihrer Utility-Toolbox mit all den anderen nützlichen Schnipseln. Bingo! Sie haben gerade Guava / Commons-Lang / was auch immer neu erfunden... nur nicht so gut. Importieren Sie stattdessen eine vernünftige Utility-Bibliothek und erfinden Sie das Rad nicht neu. Das wahre Zeichen eines Anfängers ist es, zu glauben, dass man es besser machen kann als die Autoren der Bibliothek.
2 Stimmen
NB: Das Prinzip der einzigen Abstraktionsebene ist der Grund dafür, dass diese Art von Dingen nicht berücksichtigt werden sollte. Erleichtert die Lesbarkeit und Testbarkeit, deckt wiederverwendbare Elemente auf. Siehe: slideshare.net/guestebde/10-ways-to-improve-your-code-
16 Stimmen
@AndrewSpencer Ich verstehe nicht, warum ihr so sehr versucht, StijndeWitt dafür zu beschimpfen, dass er dies mit einem kleinen Schnipsel erreichen will. Es besteht wirklich keine große Gefahr, eine winzige Utility-Methode zu schreiben (ich sehe es nicht als "Reine ARROGANZ, oh nein, er denkt, er sei besser als Apache"). Es gibt tonnenweise Projekte, vor allem in Nicht-Java-JVM-Sprachen, die wirklich nicht Guava oder Commons Lang einbinden wollen, nur um einen Stacktrace zu protokollieren. Ich schreibe Scala- und Clojure-Bibliotheken und werde sicherlich nicht Apache Commons Lang zu einer transitiven Abhängigkeit nur für eine Methode machen.
1 Stimmen
@jm0 Kein Bashing, nur eine qualifizierte Meinungsverschiedenheit. Es war ein bisschen zu schnippisch, ich war auf einen Kampf aus, nachdem ich einige schlechte selbstgebaute Dienstprogramme gesehen hatte. Ich stimme zu, dass es Gründe gibt, eine Abhängigkeit nicht hinzuzufügen, ich sehe nur häufiger den gegenteiligen Fehler.
0 Stimmen
@Gewure Unser Wissen und unser Verständnis des Codes sind heute so viel weiter entwickelt und fortgeschritten. Wir brauchen solche belanglosen Fragen nicht mehr. Lasst das gemeine Volk in seinen Unzulänglichkeiten verrotten.
1 Stimmen
Ich bin hierher gekommen, weil man beim Schreiben von Amazon Lambda-Funktionen in Java den Import von Bibliotheken vermeiden sollte, da sie die Startzeit des Containers in die Höhe treiben. Manchmal ist es also notwendig, das Rad neu zu erfinden. Oder vielleicht könnte ich das mit ProGuard lösen...
0 Stimmen
@Andrew ich weiß nicht, ob ich deinen Sarkasmus? richtig interpretiere, aber ich denke, du hast mich auch nicht richtig interpretiert: Ich wollte sagen, dass SO ein Problem hat. Es ist in der Tat elitär geworden. Es versagt völlig dabei, eine Verbindung für Neulinge zu öffnen. Sie wollten z.B. kein nicht-englisches SO. Das ist undemokratisch und elitär. Es gibt Leute, die programmieren können/wollen, aber kein richtiges Englisch sprechen.
1 Stimmen
@Gewure Es wäre hilfreich gewesen, wenn du deinen Kommentar nicht gelöscht hättest... Es war aber offensichtlich Sarkasmus. S.O. war schon immer voll von elitären und engstirnigen Snobs. Das ist nicht wirklich die Schuld von S.O., denke ich, sondern nur ein allgemeiner Fehler der Menschheit, der hier sehr deutlich zur Schau gestellt wird. Was die englische Sprache betrifft, so gibt es auf beiden Seiten eine gewisse Sensibilität; ich kann allerdings nur über das Argument selbst sprechen.
3 Stimmen
Verwenden Sie commons-lang. Josh Bloch sagt: "Wenn Sie etwas tun müssen, das relativ häufig vorkommt, gibt es vielleicht schon eine Klasse in den Bibliotheken, die das tut, was Sie wollen. Wenn das der Fall ist, verwenden Sie sie; wenn Sie es nicht wissen, überprüfen Sie es.[...]Bibliothekscode ist wahrscheinlich besser als Code, den Sie selbst schreiben würden, und wird wahrscheinlich im Laufe der Zeit verbessert.Das ist keine Aussage über Ihre Fähigkeiten als Programmierer.Skaleneffekte diktieren, dass Bibliothekscode weit mehr Aufmerksamkeit erhält, als die meisten Entwickler es sich leisten könnten, der gleichen Funktionalität zu widmen."