の結果をThrowable.getStackTrace()
スタックトレースを表す文字列に変換する最も簡単な方法は何ですか?
の結果をThrowable.getStackTrace()
スタックトレースを表す文字列に変換する最も簡単な方法は何ですか?
回答:
Exception
スタックトレースをに変換するには、次のメソッドを使用できますString
。このクラスは、Apache commons-langで使用できます。Apachecommons-langは、多くの一般的なオープンソースを備えた最も一般的な依存ライブラリです。
org.apache.commons.lang.exception.ExceptionUtils.getStackTrace(Throwable)
org.apache.commons.lang3.exception.ExceptionUtils
ます。
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
とPrintWriter
?
これはうまくいくはずです:
StringWriter sw = new StringWriter();
e.printStackTrace(new PrintWriter(sw));
String exceptionAsString = sw.toString();
printStackTrace
は単に文字列を返し、それを印刷するかどうかの決定をユーザーに残す必要があります:)
printXXX()
XXXを出力する必要があります。
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)
Log.e("TAG", "My message", new Throwable());
Throwables
クラス実際のThrowable
インスタンスがある場合、Google GuavaはThrowables.getStackTraceAsString()
。
例:
String s = Throwables.getStackTraceAsString ( myException ) ;
警告:原因は含まれていません(通常は役立ちます)。
public String stackTraceToString(Throwable e) {
StringBuilder sb = new StringBuilder();
for (StackTraceElement element : e.getStackTrace()) {
sb.append(element.toString());
sb.append("\n");
}
return sb.toString();
}
String.format("%n")
に、代わりにまたは同様のものを使用してください"\n"
。
私にとって最もクリーンで簡単な方法は:
import java.util.Arrays;
Arrays.toString(e.getStackTrace());
public static String getStackTrace(Throwable t) {
StringWriter sw = new StringWriter();
t.printStackTrace(new PrintWriter(sw));
return sw.toString();
}
StringWriter
およびPrintWriter
オブジェクトはclose
d ....であるPrintWriter
必要があることを指摘していることを指摘したいと思います(または、閉じる必要もあるので、閉じる必要もありStringWriter
ます)
次のコードを使用すると、String
log4JなどのAPIを使用することなく、stackTrace全体をフォーマットで取得できます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.
}
以下は、コードに直接コピーして貼り付けることができるバージョンです。
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());
}
Throwable
で定義されていますか?
Arrays.toString(thrown.getStackTrace())
結果を文字列に変換する最も簡単な方法です。これをプログラムで使用して、スタックトレースを出力します。
LOGGER.log(Level.SEVERE, "Query Builder Issue Stack Trace : {0} ,Message : {1} objid {2}", new Object[]{Arrays.toString(e.getStackTrace()), e.getMessage(),objId});
スタックトレースを文字列に出力する
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
。
private String getCurrentStackTraceString() {
StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace();
return Arrays.stream(stackTrace).map(StackTraceElement::toString)
.collect(Collectors.joining("\n"));
}
コメントの最初のセットでの巧妙な狙いは非常に面白いですが、それはあなたが何をしようとしているのかに本当に依存しています。正しいライブラリがまだない場合は、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)
それは私のベーコンを救った。ヒントをありがとう、アマール!
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();
}
他の回答との違いは、で使用 autoFlush
することPrintWriter
です。
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)
Scalaバージョン
def stackTraceToString(e: Exception): String = {
import java.io.PrintWriter
val sw = new StringWriter()
e.printStackTrace(new PrintWriter(sw))
sw.toString
}
Java 8を使用している場合は、これを試してください
Arrays.stream(e.getStackTrace())
.map(s->s.toString())
.collect(Collectors.joining("\n"));
あなたはとしてgetStackTrace()
提供さThrowable.java
れる関数のコードを見つけることができます:
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)")));
}
したがってStackTraceElement
、 "\ n"で結合します。
例外の原因も含まれる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;
}
Java 8 Stream APIを使用すると、次のようなことができます。
Stream
.of(throwable.getStackTrace())
.map(StackTraceElement::toString)
.collect(Collectors.joining("\n"));
スタックトレース要素の配列を取得して文字列に変換し、複数行の文字列に結合します。
外部ライブラリを使用せず、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);
}
}
}
このクラスは、Regex contains
またはその他の基準でフィルターで除外するように簡単に調整できることに注意してください。また、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);
}
}
}
プログラムを実行すると、出力は次のようになります。
java.lang.ArithmeticException: / by zero
at PrintStackTrace.main(PrintStackTrace.java:9)
警告:これは少し外れたトピックかもしれませんが、まあ...;)
元のポスターの理由がそもそもスタックトレースを文字列として必要とした理由がわかりません。スタックトレースが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
}
外部ライブラリを必要としないため、私はそれが好きです(もちろん、とにかくほとんどの場合に配置されるロギングバックエンド以外)。
いくつかのオプション
StringWriter sw = new StringWriter();
e.printStackTrace(new PrintWriter(sw));
String exceptionAsString = sw.toString();
Google Guava libの使用
String stackTrace = Throwables.getStackTraceAsString ( myException ) ;
org.apache.commons.lang.exception.ExceptionUtils.getStackTrace(Throwable)