Sonucunu Throwable.getStackTrace()
stacktrace öğesini gösteren bir dizeye dönüştürmenin en kolay yolu nedir ?
Sonucunu Throwable.getStackTrace()
stacktrace öğesini gösteren bir dizeye dönüştürmenin en kolay yolu nedir ?
Yanıtlar:
Bir Exception
yığın izlemesi dönüştürmek için aşağıdaki yöntemi kullanabilirsiniz String
. Bu sınıf, birçok popüler açık kaynakla en yaygın bağımlı kütüphane olan Apache commons-lang'da mevcuttur.
org.apache.commons.lang.exception.ExceptionUtils.getStackTrace(Throwable)
org.apache.commons.lang3.exception.ExceptionUtils
.
Throwable.printStackTrace(PrintWriter pw)
Yığın izini uygun bir yazara göndermek için kullanın .
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
ve PrintWriter
?
Bu çalışmalı:
StringWriter sw = new StringWriter();
e.printStackTrace(new PrintWriter(sw));
String exceptionAsString = sw.toString();
printStackTrace
sadece dize döndürmeli, kullanıcıya yazdırıp yazdırmamaya karar vermelidir :)
printXXX()
XXX yazdırmalıdır.
Android için geliştiriyorsanız, bunu kullanmanın çok daha kolay bir yolu vardır:
import android.util.Log;
String stackTrace = Log.getStackTraceString(exception);
Biçim getStacktrace ile aynıdır, örneğin;
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
sınıfıGerçek Throwable
örneğiniz varsa, Google Guava bunu sağlar Throwables.getStackTraceAsString()
.
Misal:
String s = Throwables.getStackTraceAsString ( myException ) ;
UYARI: Nedeni içermez (genellikle yararlı olanıdır!)
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")
veya benzer bir şey kullanın "\n"
.
Benim için en temiz ve en kolay yol:
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
ve PrintWriter
nesneler olmalı close
.... d (veya ben sadece tahmin PrintWriter
bu kapatmalıdır kapanış beri kapalı olması ihtiyacını StringWriter
da)
Aşağıdaki kod log4J String
gibi API'leri kullanmadan stackTrace öğesinin tamamını bir formatla almanıza olanak tanır 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.
}
İşte doğrudan koda kopyalanabilen bir sürüm:
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());
Veya bir yakalama bloğunda
} catch (Throwable t) {
StringWriter sw = new StringWriter();
t.printStackTrace(new PrintWriter(sw));
logger.info("Current stack trace is:\n" + sw.toString());
}
Throwable
tanımlanır, değil mi?
Arrays.toString(thrown.getStackTrace())
Sonuç Dize dönüştürmek için en kolay yolu yığın izini yazdırmak için bu benim programında kullanıyorum
LOGGER.log(Level.SEVERE, "Query Builder Issue Stack Trace : {0} ,Message : {1} objid {2}", new Object[]{Arrays.toString(e.getStackTrace()), e.getMessage(),objId});
Yığın izini a'ya yazdırın PrintStream
, ardından a'ya dönüştürün String
:
// ...
catch (Exception e)
{
ByteArrayOutputStream out = new ByteArrayOutputStream();
e.printStackTrace(new PrintStream(out));
String str = new String(out.toByteArray());
System.out.println(str);
}
Yığının izini dizeye yazdırma
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);
}
}
}
Geçerli iş parçacığı yığın izini, örneği oluşturmadan yazdırmak istediğinizde kullanışlıdır Throwable
- ancak yeni oluşturmanın Throwable
ve yığın izlemesini oradan çağırmanın aslında çağrıdan daha hızlı ve daha ucuz olduğunu unutmayın Thread.getStackTrace
.
private String getCurrentStackTraceString() {
StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace();
return Arrays.stream(stackTrace).map(StackTraceElement::toString)
.collect(Collectors.joining("\n"));
}
İlk yorum grubundaki akıllı keskin nişancı çok eğlenceliydi, ama gerçekten ne yapmaya çalıştığınıza bağlı. Zaten doğru kütüphaneye sahip değilseniz, 3 satırlık kod (D. Wroblewski'nin cevabında olduğu gibi) mükemmeldir. OTOH, zaten apache.commons kütüphanesine sahipseniz (çoğu büyük projede olduğu gibi), Amar'ın cevabı daha kısadır. Tamam, kitaplığı almanız ve doğru şekilde yüklemeniz on dakika sürebilir (ne yaptığınızı biliyorsanız birden az). Ancak saat geçiyor, bu yüzden boş zamanınız olmayabilir. Jarek Przygódzki'nin ilginç bir uyarısı vardı - "İç içe istisnalara ihtiyacınız yoksa".
Ama ne olur do tam yığın iç içe izleri ve tüm ihtiyaç? Bu durumda, sır apache.common'un getFullStackTrace'ini kullanmaktır (bkz. Http://commons.apache.org/proper/commons-lang/javadocs/api-2.6/org/apache/commons/lang/exception/ExceptionUtils.html # getFullStackTrace% 28java.lang.Throwable% 29 )
Pastırmamı kurtardı. Teşekkürler Amar, ipucu için!
Apache Commons Lang 3.4'ten ( JavaDoc ) kod :
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();
}
Diğer cevaplarla farkı , autoFlush
üzerinde kullanmasıdırPrintWriter
.
Onsuz java.io.*
böyle yapılabilir.
String trace = e.toString() + "\n";
for (StackTraceElement e1 : e.getStackTrace()) {
trace += "\t at " + e1.toString() + "\n";
}
Ve sonra trace
değişken yığın izinizi tutar. Çıktı ayrıca ilk nedeni tutar, çıktı aynıdırprintStackTrace()
Örnek, printStackTrace()
verimler:
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
Basılı String tutarstdout
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 versiyonu
def stackTraceToString(e: Exception): String = {
import java.io.PrintWriter
val sw = new StringWriter()
e.printStackTrace(new PrintWriter(sw))
sw.toString
}
Java 8 kullanıyorsanız bunu deneyin
Arrays.stream(e.getStackTrace())
.map(s->s.toString())
.collect(Collectors.joining("\n"));
getStackTrace()
fonksiyonun kodunu şu şekilde bulabilirsiniz Throwable.java
:
public StackTraceElement[] getStackTrace() {
return getOurStackTrace().clone();
}
ve StackTraceElement
bunun için sağlayıcılar toString()
:
public String toString() {
return getClassName() + "." + methodName +
(isNativeMethod() ? "(Native Method)" :
(fileName != null && lineNumber >= 0 ?
"(" + fileName + ":" + lineNumber + ")" :
(fileName != null ? "("+fileName+")" : "(Unknown Source)")));
}
Yani StackTraceElement
"\ n" ile katılın .
Gala'nın cevabında istisna nedenlerini de içerecek bir genişleme:
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;
}
Çözüm dizinin stackTrace değerini dize veri türüne dönüştürmektir. Aşağıdaki örneğe bakın:
import java.util.Arrays;
try{
}catch(Exception ex){
String stack = Arrays.toString(ex.getStackTrace());
System.out.println("stack "+ stack);
}
Java 8 Stream API ile şöyle bir şey yapabilirsiniz:
Stream
.of(throwable.getStackTrace())
.map(StackTraceElement::toString)
.collect(Collectors.joining("\n"));
Yığın izleme öğeleri dizisini alır, bunları dizeye dönüştürür ve çok satırlı dizeye katılır.
Yığın izlemesini ekteki çok satırlı dizeye dönüştürmek için benim oneliner'ım:
Stream.of(e.getStackTrace()).map((a) -> a.toString()).collect(Collectors.joining("\n", "[", "]"))
Kaydediciye "olduğu gibi" geçmek kolaydır.
printStackTrace()
Buradan farklı bir şey elde edeceksiniz: 1) Atılan istisna; 2) Nedenleri ve
printStackTrace()
Asla dönüştürmek sorunun bir parçası olmadığı için , fark oldukça beklenir .
Harici bir kütüphane kullanmak istemiyorsanız ve Android için geliştirmiyorsanız , aşağıdaki gibi bir 'uzantı' yöntemi oluşturabilirsiniz :
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();
}
Eski soru, ama tüm yığını yazdırmak istemediğiniz özel durumu eklemek istiyorum ilgilendiğiniz bazı parçaları kaldırarak, sınıfları veya paketleri hariç tutarak, .
Kullanım yerine PrintWriter
a 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);
Nerede SelectivePrintWriter
sınıf verilir:
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);
}
}
}
Lütfen bu sınıfın Regex contains
veya diğer ölçütlere göre filtrelenecek şekilde kolayca uyarlanabileceğini unutmayın . Ayrıca, Throwable
uygulama ayrıntılarına bağlı olduğunu da unutmayın (değişme olasılığı yoktur, ancak yine de).
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);
}
}
}
Programı çalıştırdığınızda, çıktı benzer bir şey olacaktır:
java.lang.ArithmeticException: / by zero
at PrintStackTrace.main(PrintStackTrace.java:9)
Merak ediyorum neden kimse söylemedi ExceptionUtils.getStackFrames(exception)
Benim için yığın izini sonuna kadar tüm nedenleriyle boşaltmanın en uygun yolu:
String.join("\n", ExceptionUtils.getStackFrames(exception));
Uyarı: Bu biraz konu olabilir, ama oh iyi ...;)
İlk etapta dize olarak yığın izini istemek için orijinal posterlerin nedeninin ne olduğunu bilmiyorum . Yığın izleme bir SLF4J / Logback LOG ile bitmelidir, ancak bir istisna yoktu veya atılmalıdır ne yapıyorum:
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
}
Bunu seviyorum çünkü harici bir kütüphane gerektirmiyor (elbette çoğu zaman yerinde olacak olan kayıt arka uçunuz dışında).
Birkaç seçenek
StringWriter sw = new StringWriter();
e.printStackTrace(new PrintWriter(sw));
String exceptionAsString = sw.toString();
Google Guava lib'i kullanma
String stackTrace = Throwables.getStackTraceAsString ( myException ) ;
org.apache.commons.lang.exception.ExceptionUtils.getStackTrace (Throwable)