วิธีแสดงข้อความยาวใน logcat


99

ฉันพยายามแสดงข้อความยาวบน logcat หากความยาวของข้อความมากกว่า 1,000 อักขระข้อความนั้นจะเสียหาย

กลไกในการแสดงอักขระทั้งหมดของข้อความยาวใน logcat คืออะไร?


6
ฉันได้รับคำตอบจากเซิร์ฟเวอร์เป็นสตริงแบบยาว
วสุ

1
ถึงอย่างนั้นทำไมคุณถึงต้องการพิมพ์สตริงทั้งหมดเขียนลงในไฟล์หรือฐานข้อมูลและดูที่นั่น - หากใช้สำหรับการดีบัก
Rahul Choudhary

คัดลอกสตริง logcat ของคุณและวางลงในแผ่นจดบันทึกคุณจะเห็นความยาวของสตริงเต็ม 1,000
ilango

คำตอบ:


152

หาก logcat กำหนดความยาวไว้ที่ 1,000 คุณสามารถแยกสตริงที่คุณต้องการบันทึกด้วย String.subString () และบันทึกเป็นชิ้น ๆ ตัวอย่างเช่น:

int maxLogSize = 1000;
for(int i = 0; i <= veryLongString.length() / maxLogSize; i++) {
    int start = i * maxLogSize;
    int end = (i+1) * maxLogSize;
    end = end > veryLongString.length() ? veryLongString.length() : end;
    Log.v(TAG, veryLongString.substring(start, end));
}

Log cat พิมพ์เพียงครึ่งเดียวของการตอบกลับ .. ฉันจะได้รับความยาวของคำตอบทั้งหมดได้อย่างไร คุณบอกว่า veryLongString.length () แต่ที่นี่พิมพ์เพียงครึ่งเดียวของการตอบสนองเมื่อฉันพิมพ์ผล json ใน log cat
วสุ

แต่ในคอนโซล iphone ฉันได้รับสตริงการตอบกลับทั้งหมด
วสุ

คุณสามารถตรวจสอบความยาวของคำตอบได้โดยเขียน length () ลงในบันทึก หากค่านี้ไม่เป็นไปตามที่คุณคาดไว้ปัญหาอาจไม่ได้อยู่ที่การบันทึก
spatulamania

3
ไม่อยากจะเชื่อเลยว่า Android ทำให้มันยากขนาดนี้!
Alston

1
ฉันคิดว่ารหัสนี้จะบันทึกรายการบันทึกพิเศษที่ว่างเปล่าในตอนท้ายหากveryLongString.length()เป็นไฟล์maxLogSize. อาจจะเปลี่ยนไป<= <
LarsH

31

ตามคำตอบของ spatulamania ฉันเขียนคลาสกระดาษห่อที่จัดการสิ่งนี้ให้คุณ คุณเพียงแค่ต้องเปลี่ยนการนำเข้าและจะบันทึกทุกอย่าง

public class Log {

    public static void d(String TAG, String message) {
        int maxLogSize = 2000;
        for(int i = 0; i <= message.length() / maxLogSize; i++) {
            int start = i * maxLogSize;
            int end = (i+1) * maxLogSize;
            end = end > message.length() ? message.length() : end;
            android.util.Log.d(TAG, message.substring(start, end));
        }
    }

}

24

สิ่งนี้สร้างจากคำตอบของ spatulamania สั้นกว่าเล็กน้อยและจะไม่เพิ่มข้อความบันทึกที่ว่างเปล่าในตอนท้าย:

final int chunkSize = 2048;
for (int i = 0; i < s.length(); i += chunkSize) {
    Log.d(TAG, s.substring(i, Math.min(s.length(), i + chunkSize)));
}

ขอบคุณ. ไม่แนะนำให้ใช้สัญลักษณ์มากกว่า 3,000 สัญลักษณ์ฉันใช้อย่างนั้น
CoolMind

9

นี่คือวิธีที่ OkHttp กับ HttpLoggingInterceptor ทำ:

public void log(String message) {
  // Split by line, then ensure each line can fit into Log's maximum length.
  for (int i = 0, length = message.length(); i < length; i++) {
    int newline = message.indexOf('\n', i);
    newline = newline != -1 ? newline : length;
    do {
      int end = Math.min(newline, i + MAX_LOG_LENGTH);
      Log.d("OkHttp", message.substring(i, end));
      i = end;
    } while (i < newline);
  }
}

MAX_LOG_LENGTH คือ 4000

ที่นี่ใช้ Log.d (debug) และแท็ก "OkHttp" ที่เข้ารหัส

มันแยกบันทึกที่ขึ้นบรรทัดใหม่หรือเมื่อถึงความยาวสูงสุด

คลาสด้านล่างนี้เป็นคลาสตัวช่วยที่คุณสามารถใช้ได้ (ถ้าคุณมีแลมด้าซัพพอร์ทให้โยน Jack & Jill หรือ retrolambda) เพื่อทำสิ่งเดียวกันกับที่ OkHttp ทำในบันทึกใด ๆ :

/**
 * Help printing logs splitting text on new line and creating multiple logs for too long texts
 */

public class LogHelper {

    private static final int MAX_LOG_LENGTH = 4000;

    public static void v(@NonNull String tag, @Nullable String message) {
        log(message, line -> Log.v(tag, line));
    }

    public static void d(@NonNull String tag, @Nullable String message) {
        log(message, line -> Log.d(tag, line));
    }

    public static void i(@NonNull String tag, @Nullable String message) {
        log(message, line -> Log.i(tag, line));
    }

    public static void w(@NonNull String tag, @Nullable String message) {
        log(message, line -> Log.w(tag, line));
    }

    public static void e(@NonNull String tag, @Nullable String message) {
        log(message, line -> Log.e(tag, line));
    }

    public static void v(@NonNull String tag, @Nullable String message, @Nullable Throwable throwable) {
        log(message, throwable, line -> Log.v(tag, line));
    }

    public static void d(@NonNull String tag, @Nullable String message, @Nullable Throwable throwable) {
        log(message, throwable, line -> Log.d(tag, line));
    }

    public static void i(@NonNull String tag, @Nullable String message, @Nullable Throwable throwable) {
        log(message, throwable, line -> Log.i(tag, line));
    }

    public static void w(@NonNull String tag, @Nullable String message, @Nullable Throwable throwable) {
        log(message, throwable, line -> Log.w(tag, line));
    }

    public static void e(@NonNull String tag, @Nullable String message, @Nullable Throwable throwable) {
        log(message, throwable, line -> Log.e(tag, line));
    }

    private static void log(@Nullable String message, @NonNull LogCB callback) {
        if (message == null) {
            callback.log("null");
            return;
        }
        // Split by line, then ensure each line can fit into Log's maximum length.
        for (int i = 0, length = message.length(); i < length; i++) {
            int newline = message.indexOf('\n', i);
            newline = newline != -1 ? newline : length;
            do {
                int end = Math.min(newline, i + MAX_LOG_LENGTH);
                callback.log(message.substring(i, end));
                i = end;
            } while (i < newline);
        }
    }

    private static void log(@Nullable String message, @Nullable Throwable throwable, @NonNull LogCB callback) {
        if (throwable == null) {
            log(message, callback);
            return;
        }
        if (message != null) {
            log(message + "\n" + Log.getStackTraceString(throwable), callback);
        } else {
            log(Log.getStackTraceString(throwable), callback);
        }
    }

    private interface LogCB {
        void log(@NonNull String message);
    }
}

ฉันค้นหาด้วยตัวเองในรหัสของพวกเขา แต่ไม่พบ ขอขอบคุณ.
Bugs เกิดขึ้น

8

ลองใช้โค้ดนี้เพื่อแสดงข้อความยาวใน logcat

public void logLargeString(String str) {
    if(str.length() > 3000) {
        Log.i(TAG, str.substring(0, 3000));
        logLargeString(str.substring(3000));
    } else {
        Log.i(TAG, str); // continuation
    }
}

7
เมื่อการวนซ้ำธรรมดาเพียงพอทำไมจึงต้องใช้การวนซ้ำ
pellucide

3
ฉันเป็นแฟนตัวยงของการเรียกซ้ำเนื่องจากฉันพบว่าการอ่านง่ายและการนำโค้ดกลับมาใช้ใหม่นั้นยอดเยี่ยม อย่างไรก็ตามการเรียกซ้ำปลายหางนี้สามารถสร้างสแต็กเฟรมได้อย่างรวดเร็วหากคอมไพเลอร์ของคุณไม่ได้ปรับให้เหมาะสม (ซึ่งฉันไม่เชื่อว่าสตูดิโอ Android ทำ) ซึ่งหมายความว่าหากคุณมีข้อความยาวมากที่ทำให้เกิดการเรียกซ้ำหลายครั้งคุณสามารถสร้าง StackOverflowError ได้อย่างง่ายดาย
ลุค

3

เพื่อไม่ให้มีการแบ่งบรรทัดในข้อความบันทึกน้อยที่สุดฉันจึงใช้สตริงขนาดใหญ่และบันทึกแต่ละบรรทัดแยกกัน

void logMultilineString(String data) {
    for (String line : data.split("\n")) {
        logLargeString(line);
    }
}

void logLargeString(String data) {
    final int CHUNK_SIZE = 4076;  // Typical max logcat payload.
    int offset = 0;
    while (offset + CHUNK_SIZE <= data.length()) {
        Log.d(TAG, data.substring(offset, offset += CHUNK_SIZE));
    }
    if (offset < data.length()) {
        Log.d(TAG, data.substring(offset));
    }
}

1

นี่คือเวอร์ชัน Kotlin สำหรับคำตอบ @spatulamania (โดยเฉพาะสำหรับคนขี้เกียจ / ฉลาด):

val maxLogSize = 1000
val stringLength = yourString.length
for (i in 0..stringLength / maxLogSize) {
    val start = i * maxLogSize
    var end = (i + 1) * maxLogSize
    end = if (end > yourString.length) yourString.length else end
    Log.v("YOURTAG", yourString.substring(start, end))
}

1

ฉันถือว่าไม้เป็นตัวเลือกที่ดีสำหรับปัญหานี้ Timber จะแยกและพิมพ์ข้อความใน logcat โดยอัตโนมัติ

https://github.com/JakeWharton/timber

คุณสามารถดูการนำเมธอดไปใช้ในคลาสแบบคงที่ timber.log.Timber.DebugTree


0

หากพิมพ์สตริง json สามารถใช้รหัสด้านล่าง

    @JvmStatic
    fun j(level: Int, tag: String? = null, msg: String) {
        if (debug) {
            if (TextUtils.isEmpty(msg)) {
                p(level, tag, msg)
            } else {
                val message: String
                message = try {
                    when {
                        msg.startsWith("{") -> {
                            val jsonObject = JSONObject(msg)
                            jsonObject.toString(4)
                        }
                        msg.startsWith("[") -> {
                            val jsonArray = JSONArray(msg)
                            jsonArray.toString(4)
                        }
                        else -> msg
                    }
                } catch (e: JSONException) {
                    e.printStackTrace()
                    msg
                }
                p(level, tag, "╔═══════════════════════════════════════════════════════════════════════════════════════", false)
                val lines = message.split(LINE_SEPARATOR.toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray()
                for (line in lines) {
                    p(level, tag, "║ $line", false)
                }
                p(level, tag, "╚═══════════════════════════════════════════════════════════════════════════════════════", false)
            }
        }
    }

รหัสเต็ม

CXLogUtil.j ("json-tag", "{}")

ดูตัวอย่างผลลัพธ์


-3

สำหรับวิธีแก้ปัญหาที่ง่ายให้ใช้ตัวเลือกใช้การห่อแบบนุ่มที่ด้านล่างจุดแนบหมายเลข 4 ตัวเลือกอาจช่วยคุณได้

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.