เป็นวิธีที่ง่ายที่สุดในการแปลงผลลัพธ์ของThrowable.getStackTrace()
การเป็นสายอักขระที่แสดงให้เห็นถึง stacktrace อะไร
เป็นวิธีที่ง่ายที่สุดในการแปลงผลลัพธ์ของThrowable.getStackTrace()
การเป็นสายอักขระที่แสดงให้เห็นถึง stacktrace อะไร
คำตอบ:
หนึ่งสามารถใช้วิธีการต่อไปนี้เพื่อแปลงกองติดตามไปException
String
คลาสนี้มีอยู่ในApache Commons-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 ฝรั่ง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"
การทำให้ DOS lamers มีความสุข
สำหรับฉันวิธีที่สะอาดและง่ายที่สุดคือ:
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
เช่นกัน)
รหัสต่อไปนี้ช่วยให้คุณได้รับทั้ง stackTrace ด้วยString
รูปแบบโดยไม่ต้องใช้ API เช่น log4J หรือแม้กระทั่ง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())
เป็นวิธีที่ง่ายที่สุดในการแปลงผลลัพธ์เป็น String I ที่ใช้ในโปรแกรมของฉันเพื่อพิมพ์ 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});
พิมพ์ stack trace เป็น a PrintStream
จากนั้นแปลงเป็น a String
:
// ...
catch (Exception e)
{
ByteArrayOutputStream out = new ByteArrayOutputStream();
e.printStackTrace(new PrintStream(out));
String str = new String(out.toByteArray());
System.out.println(str);
}
การพิมพ์การติดตามสแต็กเป็นสตริง
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
การขยายคลาส Throwable จะทำให้คุณมีคุณสมบัติ String error.stackTraceString
:
val Throwable.stackTraceString: String
get() {
val sw = StringWriter()
val pw = PrintWriter(sw)
this.printStackTrace(pw)
return sw.toString()
}
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 ก็จะสั้นลง ตกลงอาจใช้เวลาสิบนาทีในการรับห้องสมุดและติดตั้งอย่างถูกต้อง (น้อยกว่าหนึ่งถ้าคุณรู้ว่าคุณกำลังทำอะไรอยู่) แต่นาฬิกากำลังฟ้องดังนั้นคุณอาจไม่มีเวลาว่าง Jarek Przygódzkiมีข้อแม้ที่น่าสนใจ - "ถ้าคุณไม่ต้องการข้อยกเว้นซ้อน"
แต่ถ้าฉันไม่จำเป็นต้องมีร่องรอยสแต็คเต็มรูปแบบซ้อนกันและทั้งหมดหรือไม่ ในกรณีดังกล่าวความลับคือการใช้ getFullStackTrace ของ apache.com (ดูที่http://commons.apache.org/proper/commons-lang/javadocs/api-2.6/org/apache/commons/lang/exception/ExceptionUtils.html # getFullStackTrace% 28java.lang.Throwable 29% )
มันช่วยเบคอนของฉัน ขอบคุณ Amar สำหรับคำใบ้!
รหัสจาก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
String ถือเมื่อพิมพ์ไป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)
รุ่นสกาล่า
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"
exapansion ในคำตอบของ 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;
}
วิธีแก้ไขคือการแปลง stackTrace ของอาเรย์เป็นประเภทข้อมูลสตริง ดูตัวอย่างต่อไปนี้:
import java.util.Arrays;
try{
}catch(Exception ex){
String stack = Arrays.toString(ex.getStackTrace());
System.out.println("stack "+ stack);
}
ด้วย Java 8 Stream APIคุณสามารถทำสิ่งนี้:
Stream
.of(throwable.getStackTrace())
.map(StackTraceElement::toString)
.collect(Collectors.joining("\n"));
มันจะใช้อาร์เรย์ขององค์ประกอบการติดตามสแต็คแปลงเป็นสตริงและเข้าร่วมเป็นสตริงหลายบรรทัด
Oneliner ของฉันเพื่อแปลงการติดตามสแต็กเป็นสตริงที่มีหลายบรรทัด:
Stream.of(e.getStackTrace()).map((a) -> a.toString()).collect(Collectors.joining("\n", "[", "]"))
ง่ายต่อการส่งผ่านไปยังคนตัดไม้ "ตามที่เป็น"
printStackTrace()
นี่คุณจะหลวม: 1) ข้อยกเว้นที่ถูกโยน; 2) สาเหตุและ stacktrace ของพวกเขา
printStackTrace()
ไม่เคยเป็นส่วนหนึ่งของคำถาม
หากคุณไม่ต้องการใช้ห้องสมุดภายนอกและคุณไม่ได้พัฒนาสำหรับ 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)
ฉันสงสัยว่าทำไมไม่มีใครพูดถึง ExceptionUtils.getStackFrames(exception)
สำหรับฉันมันเป็นวิธีที่สะดวกที่สุดในการถ่ายโอน stacktrace ด้วยสาเหตุทั้งหมดจนถึงที่สุด:
String.join("\n", ExceptionUtils.getStackFrames(exception));
คำเตือน: นี่อาจจะเป็นหัวข้อเล็กน้อย แต่ก็ดี ... ;)
ฉันไม่ทราบว่าเหตุผลดั้งเดิมของผู้โพสต์คือต้องการให้ร่องรอยสแต็กเป็นสตริงในตอนแรก เมื่อการติดตามสแต็คควรจบลงใน 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)