日志格式化技巧:参数占位符%s、%d使用、打印对象与数组、格式化输出对齐
日志格式化,说白了就是让日志说人话。
我刚开始做鸿蒙开发时,也踩过不少坑。那时候打印日志全靠拼字符串,代码里全是 "用户ID:" + userId + ",姓名:" + name 这种写法。后来发现,日志一多,眼睛都看花了。嗯,格式化才是正解。
一、参数占位符:%s 和 %d 的正确打开方式
鸿蒙的 HiLog 支持两种最常用的占位符:%s 和 %d。前者管字符串,后者管整数。用法很简单,但细节决定成败。
// 基础用法
HiLog.info(LABEL, "用户登录:账号 = %s,尝试次数 = %d", account, retryCount);
// 多个占位符,按顺序对应
HiLog.info(LABEL, "请求耗时:%d ms,状态码 = %d,描述 = %s", costTime, statusCode, description);
我个人习惯把占位符当成「填空游戏」。你挖几个坑,后面就填几个参数。顺序不能乱,类型要对上。
用 %d 打印 long 类型变量,结果输出了一串乱码。后来才发现,long 类型要用 %ld。鸿蒙的 HiLog 对类型要求比较严格,别偷懒。
如果你不确定某个变量该用哪个占位符,先试试 %s。它会调用对象的 toString() 方法,至少不会崩溃。当然,性能上会差一点点。
二、打印对象与数组:别让日志变成天书
你想想看,如果日志里全是 com.example.User@1a2b3c 这种地址,调试起来得多痛苦?
打印对象,核心思路是重写 toString() 方法。鸿蒙的 Java 层和 ArkTS 层都支持。
// Java 层:重写 toString()
public class User {
private String name;
private int age;
@Override
public String toString() {
return "User{name='" + name + "', age=" + age + "}";
}
}
// 打印时直接传对象
HiLog.info(LABEL, "当前用户信息:%s", user);
// ArkTS 层:使用 JSON.stringify()
let userInfo = {
name: "张三",
age: 28,
roles: ["admin", "editor"]
};
HiLog.info(LABEL, "用户数据:%s", JSON.stringify(userInfo));
打印数组也类似。我建议用 Arrays.toString() 或者 JSON.stringify(),别自己写循环拼接。
// Java 数组打印
int[] scores = {85, 92, 78, 90};
HiLog.info(LABEL, "成绩列表:%s", Arrays.toString(scores));
// 多维数组用 Arrays.deepToString()
int[][] matrix = {{1,2}, {3,4}};
HiLog.info(LABEL, "矩阵数据:%s", Arrays.deepToString(matrix));
日志里出现的对象,一定要能看出「这是什么」。如果 toString() 返回的是无意义的内容,那这个日志等于白写。
三、格式化输出对齐:让日志整整齐齐
日志一多,最怕什么?最怕对不齐。你看一眼日志,左边歪歪扭扭,右边参差不齐,找关键信息全靠肉眼扫描。太累了。
格式化对齐,说白了就是给每个字段分配固定的宽度。鸿蒙的 HiLog 本身不支持 printf 那种 %-10s 的写法,但我们可以自己动手。
// 手动对齐:固定宽度
String formatLog = String.format("%-20s | %-10s | %-8s", "模块名称", "状态码", "耗时(ms)");
HiLog.info(LABEL, formatLog);
// 实际数据对齐
HiLog.info(LABEL, String.format("%-20s | %-10d | %-8d", "登录模块", 200, 35));
HiLog.info(LABEL, String.format("%-20s | %-10d | %-8d", "数据加载", 404, 1200));
HiLog.info(LABEL, String.format("%-20s | %-10d | %-8d", "图片渲染", 200, 89));
输出效果:
模块名称 | 状态码 | 耗时(ms)
登录模块 | 200 | 35
数据加载 | 404 | 1200
图片渲染 | 200 | 89
你看,整整齐齐的。一眼就能看出哪行是异常,哪行耗时高。
我会在日志开头加一个表头,然后每条数据对齐。这样日志文件打开,扫一眼就能定位问题。尤其是排查性能问题时,耗时列对齐了,谁高谁低一目了然。
四、知识体系总览
下面这张图,是我自己总结的日志格式化核心逻辑。你可以把它当成一个检查清单。
五、避坑指南:我踩过的那些坑
做日志格式化,有几个坑特别容易踩。我一个个说。
- 占位符和参数数量不匹配 —— 少传一个参数,日志直接崩。多传一个参数,后面的被忽略。我建议每次写完都数一遍。
- 对象没重写 toString() —— 打印出来全是
类名@哈希码,等于没打。尤其是自定义的实体类,一定要重写。 - 数组直接传引用 ——
HiLog.info(LABEL, "数组:%s", array)这种写法,打印出来的是地址。要用Arrays.toString()包一层。 - 对齐时中文和英文混排 —— 中文占两个字符宽度,英文占一个。用
%-20s对齐时,中文会多占位置,导致对不齐。我的解决办法是:统一用英文或数字做对齐,中文单独处理。
有一次线上排查问题,日志里打印了一个大对象,结果 toString() 里循环引用了,直接栈溢出。从那以后,我所有对象的 toString() 都只打印关键字段,绝不打印关联对象。
六、总结
日志格式化,说白了就三件事:
- 占位符用对,类型匹配
- 对象和数组要能看懂
- 输出要对齐,一眼能定位
做到这三点,你的日志就不再是「天书」,而是真正的调试利器。
公众号:蓝海资料掘金营,微信deep3321