如何解决 Android Studio 长日志打印不全问题?

    我们在开发过程中经常需要在控制台打印日志来进行调试,但是会发现日志内容过长的情况下,就无法完整的输出全部内容,这是因为 Log 日志最大长度为 4096 字节,超过这个长度的部分就无法显示。下面给出几个解决方案:

方式一:

private static final int MAX_LOG_BYTES = 4096;

public static void largeLog(String tag, String content) {
    if (content.length() > MAX_LOG_BYTES) {
        Log.d(tag, content.substring(0, MAX_LOG_BYTES));
        largeLog(tag, content.substring(MAX_LOG_BYTES));
    } else {
        Log.d(tag, content);
    }
}

    以上代码初看起来,简洁优雅,但实际上存在问题,Log 日志的最大长度 4096 是指的字节长度,如果输出的日志内容都是 ASCII 编码的字符(单字节的字符),这样写是可以的。但是如果日志内容包括 UTF8 编码的中文字符(1-4个字节),所以上面代码中的:content.substring(0, MAX_LOG_BYTES),“4096 长度的字符串”包括的字节数会超出 4096 字节(日志最大字节数),仍然会导致分段输出的日志可能不完整。

    根据上面的分析,如果输出的日志(字符串)不仅仅包括单字节字符(包括中文字符),可以考虑将上面的 MAX_LOG_BYTES 的值修改的低一些,例如1000,2000等。这样处理虽然比较简单,但略显粗糙,因此我们可以考虑用更精准的 “方式二” 与 “方式三” 来实现。

方式二:

   # 由于日志的tag, priority(assert, debug, ...), etc. 会占用一些字节,这里4096是一个理想值。
   # 建议这里设置一个小于4096 的值,例如一个比较保守的值 4000 
   # private static final int MAX_LOG_BYTES = 4096;

    private static final int MAX_LOG_BYTES = 4000;

    public static void largeLog(int priority, String tag, @NonNull String content) {

        int size = content.getBytes(StandardCharsets.UTF_8).length;
        if (size > MAX_LOG_BYTES) {
            String text = trim(content, MAX_LOG_BYTES);
            Log.println(priority, tag, text);
            largeLog(priority, tag, content.substring(text.length()));
        } else {
            Log.println(priority, tag, content);
        }

    }

    public static String trim(String text, int size) {

        byte[] inputBytes = text.getBytes(StandardCharsets.UTF_8);
        byte[] outputBytes = new byte[size];

        System.arraycopy(inputBytes, 0, outputBytes, 0, size);
        String result = new String(outputBytes, StandardCharsets.UTF_8);

        // check if last character is truncated
        int lastIndex = result.length() - 1;

        if (lastIndex > 0 && result.charAt(lastIndex) != text.charAt(lastIndex)) {
            // last character is truncated so remove the last character
            return result.substring(0, lastIndex);
        }
        return result;

    }

方式三:

   # 由于日志的tag, priority(assert, debug, ...), etc. 会占用一些字节,这里4096是一个理想值。
   # 建议这里设置一个小于4096 的值,例如一个比较保守的值 4000 
   # private static final int MAX_LOG_BYTES = 4096;

    private static final int MAX_LOG_BYTES = 4000;   

    public static void largeLog(String tag, String str) {
        String[]  logs = SplitStringByByteLength(str, "UTF-8", MAX_LOG_BYTES );
        for(String log : logs) {
            Log.i(tag, log);
        }
    }

    public static String[] SplitStringByByteLength(String src, String encoding, int maxsize) {
        Charset cs = Charset.forName(encoding);
        CharsetEncoder coder = cs.newEncoder();
        ByteBuffer out = ByteBuffer.allocate(maxsize);  // output buffer of required size
        CharBuffer in = CharBuffer.wrap(src);
        List<String> ss = new ArrayList<>();            // a list to store the chunks
        int pos = 0;
        while(true) {
            CoderResult cr = coder.encode(in, out, true); // try to encode as much as possible
            int newpos = src.length() - in.length();
            String s = src.substring(pos, newpos);
            ss.add(s);                                  // add what has been encoded to the list
            pos = newpos;                               // store new input position
            out.rewind();                               // and rewind output buffer
            if (! cr.isOverflow()) {
                break;                                  // everything has been encoded
            }
        }
        return ss.toArray(new String[0]);
    }

参考:

Android - Set max length of logcat messages

  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

思涛的博客

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值