如何为Android中java.util.logging.Formatter设置区域设置?
解决Android中java.util.logging.SimpleFormatter的区域化日期格式问题
这个问题太典型了——用java.util.logging在Android上输出自定义文件日志时,SimpleFormatter默认会用系统的区域设置格式化日期时间,结果日志里冒出非欧洲数字(比如阿拉伯-Indic数字),排查问题时看得头大。好在你已经找对了核心方向:要区分开两个名字相近但功能完全不同的类——java.util.logging.Formatter是日志框架的抽象格式化基类,而java.util.Formatter才是支持传入Locale参数的字符串格式化工具类,用Locale.ROOT就能强制生成通用的、易读的日期格式。
咱直接上可行的解决方案:自定义一个继承自SimpleFormatter的格式化类,重写它的format方法,在内部创建java.util.Formatter时指定Locale.ROOT,替换掉默认的系统Locale行为。
代码实现示例
import java.util.Locale; import java.util.Formatter; import java.util.logging.LogRecord; import java.util.logging.SimpleFormatter; import java.util.logging.Level; public class RootLocaleSimpleFormatter extends SimpleFormatter { // 复用SimpleFormatter的默认日志格式,保证结构和原日志一致 private static final String DEFAULT_FORMAT = "%1$tY-%1$tm-%1$td %1$tH:%1$tM:%1$tS %4$s %2$s: %5$s%6$s%n"; @Override public synchronized String format(LogRecord record) { // 核心改动:创建Formatter时传入Locale.ROOT,强制使用通用区域格式 try (Formatter formatter = new Formatter(Locale.ROOT)) { String throwableStr = ""; if (record.getThrown() != null) { // 复用原SimpleFormatter的堆栈跟踪格式化逻辑,保持日志风格统一 try (java.io.StringWriter sw = new java.io.StringWriter(); java.io.PrintWriter pw = new java.io.PrintWriter(sw)) { record.getThrown().printStackTrace(pw); throwableStr = "\n" + sw.toString(); } catch (java.io.IOException e) { throwableStr = "\n[Failed to format stack trace]"; } } return formatter.format(DEFAULT_FORMAT, record.getMillis(), record.getSourceClassName(), record.getSourceMethodName(), record.getLevel().getLocalizedName(), formatMessage(record), throwableStr).toString(); } } }
关键细节说明
- 我们直接复用了
SimpleFormatter的默认格式字符串,这样日志的整体结构和原来完全一致,只是把日期时间的格式化区域改成了Locale.ROOT,不用重新适配日志格式。 Locale.ROOT是Java 1.6引入的,Android从API Level 1就支持,完全不用担心兼容性问题。- 用
try-with-resources语法管理Formatter和IO流,避免资源泄漏,符合Android的最佳实践。
如何使用自定义Formatter
在配置你的FileHandler时,把自定义的格式化类设置进去即可(注意申请存储权限):
try { // 自定义日志文件路径(示例用外部存储的应用私有目录) File logFile = new File(getExternalFilesDir(null), "app_runtime.log"); // 追加模式写入日志 FileHandler fileHandler = new FileHandler(logFile.getAbsolutePath(), true); // 绑定自定义格式化器 fileHandler.setFormatter(new RootLocaleSimpleFormatter()); // 关联到目标Logger Logger appLogger = Logger.getLogger("com.your.app.package"); appLogger.addHandler(fileHandler); appLogger.setLevel(Level.ALL); } catch (IOException e) { e.printStackTrace(); }
这样输出的日志日期时间就会用通用的阿拉伯数字和标准格式,比如2024-05-20 14:30:45 INFO com.your.app.package.MainActivity: App initialized successfully,再也不会出现看不懂的区域化数字了。
内容的提问来源于stack exchange,提问作者LarsH
相关产品推荐
相关产品推荐

