Cómo mostrar mensajes largos en logcat

99

Estoy tratando de mostrar un mensaje largo en logcat. Si el mensaje tiene más de 1000 caracteres, se rompe.

¿Cuál es el mecanismo para mostrar todos los caracteres de mensaje largo en logcat?

Vasu
fuente
6
Recibo respuesta del servidor como una cadena larga.
Vasu
1
Incluso entonces, ¿por qué querría imprimir toda la cadena, escribirla en un archivo o base de datos y verla allí, si es para depuración
Rahul Choudhary
copie su cadena logcat y péguela en notpad, puede ver la longitud completa de 1000 cadenas.
ilango j
stackoverflow.com/questions/8888654/…
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功

Respuestas:

149

Si logcat limita la longitud a 1000, puede dividir la cadena que desea registrar con String.subString () y registrarla en partes. Por ejemplo:

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));
}
espátulamanía
fuente
Log cat imprimiendo solo la mitad de la respuesta. ¿Cómo puedo obtener la longitud de la respuesta completa? dijiste que veryLongString.length () pero aquí se imprime solo la mitad de la respuesta cuando imprimo el resultado json en log cat
Vasu
Pero en la consola del iPhone obtengo la cadena de respuesta completa
Vasu
puede comprobar la longitud de la respuesta escribiendo length () en el registro. Si este valor no es el esperado, es posible que el problema no sea el registro.
espátulamania
3
¡No puedo creer que Android lo haga tan difícil!
Alston
1
Creo que este código registrará una entrada de registro vacía adicional al final, si veryLongString.length()es un múltiplo de maxLogSize. Quizás cambie el <=a <.
LarsH
29

Como continuación de la respuesta de la espátulamania, escribí una clase contenedora que se encarga de esto por ti. Solo necesita cambiar la importación y registrará todo

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));
        }
    }

}
jiduvah
fuente
23

Esto se basa en la respuesta de Spatulamania, es un poco más conciso y no agregará un mensaje de registro vacío al final:

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)));
}
LarsH
fuente
Gracias. No se recomiendan más de 3000 símbolos, yo lo uso.
CoolMind
9

Así es como lo hace OkHttp con 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 es 4000.

Aquí usa Log.d (depuración) y la etiqueta "OkHttp" codificada.

Divide el registro en nuevas líneas o cuando alcanza la longitud máxima.

Esta clase a continuación es una clase auxiliar que puede usar (si tiene soporte lambda, tire Jack & Jill o retrolambda) para hacer lo mismo que OkHttp hace en cualquier registro:

/**
 * 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);
    }
}
Daniele Segato
fuente
Lo estaba buscando yo mismo en su código pero no pude encontrarlo. Gracias.
Errores ocurren
8

Pruebe este código para mostrar un mensaje largo en 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
    }
}
mani
fuente
6
cuando un bucle simple será suficiente, por qué usar la recursividad.
pellucide
3
Soy un fanático de la recursividad, ya que encuentro excelente la facilidad de uso y la reutilización del código. Sin embargo, esta recursividad final puede acumular marcos de pila rápidamente si su compilador no los optimiza (lo que no creo que haga el estudio de Android). Esto significa que si tiene un mensaje sustancialmente largo que causa un pluribus de llamadas recursivas, puede crear fácilmente un StackOverflowError.
Lucas
3

Para no minimizar la división de líneas en los mensajes de registro, tomo la cadena grande y registro cada línea por separado.

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));
    }
}
vonWippersnap
fuente
1

Aquí hay una versión de Kotlin para la respuesta de @spatulamania (especialmente para personas perezosas / inteligentes):

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))
}
Filipe Brito
fuente
1

Considero que Timber es una buena opción para este problema. Timber divide e imprime automáticamente fragmentos de mensajes en logcat.

https://github.com/JakeWharton/timber

Puede ver la implementación del método de registro en la clase estática timber.log.Timber.DebugTree.

Jaelson Wagner
fuente
0

si imprime la cadena json, puede usar el código a continuación

    @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)
            }
        }
    }

código completo

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

resultado de vista previa

Michael Mao
fuente
-2

Para una solución fácil, use la opción Usar envoltura suave en el punto de adjunto no 4 opciones que pueden ayudarlo.

Mohit Suthar
fuente