java读取.properties中文乱码的根本原因是properties默认用iso-8859-1解码,解决方案是改用load(reader)并指定utf-8编码,或手动读取字节流后解码+转义还原,避免依赖load(inputstream)。

Java 读取配置类(如 .properties 文件)时出现中文乱码,根本原因在于 java.util.Properties 的默认加载机制——它硬编码使用 ISO-8859-1 解码字节流,且不支持自动识别 UTF-8 或 GBK。这在旧版 JDK(如 JDK 8/11)中尤为突出,即使文件本身是 UTF-8 编码,load(InputStream) 方法也会错误地将多字节中文当作单字节拉丁字符解析,导致 ? 或乱码。
要优雅规避这一限制,关键不是“改 JVM 默认编码”,而是绕过 Properties.load(InputStream) 的隐式解码逻辑,改用字节流 + 显式解码的可控路径。以下是经过验证的实用方案:
明确以 UTF-8 读取字节并手动转义还原
.properties 文件若含中文,应保存为 UTF-8 无 BOM 格式。然后跳过 load(InputStream),改用 load(Reader),并确保该 Reader 使用 UTF-8 解码:
Properties props = new Properties();
try (InputStream is = getClass().getResourceAsStream("/config.properties");
Reader reader = new InputStreamReader(is, StandardCharsets.UTF_8)) {
props.load(reader); // ✅ 不走 ISO-8859-1 路径
} catch (IOException e) {
throw new RuntimeException(e);
}
⚠️ 注意:此法要求文件中中文未被 native2ascii 转义(即直接写
name=张三,而非name=\u5f20\u4e09)。若已有转义内容,仍可用此方式读取,不会破坏;但若原始文件是纯 UTF-8 明文,这是最简洁可靠的方案。
兼容已转义与未转义的混合场景(推荐用于生产)
有些项目历史遗留 .properties 同时存在 key=中文 和 key=\u4f60\u597d 形式。此时需先按 UTF-8 读取全部字节,再模拟 Properties 的 loadConvert 逻辑做 Unicode 转义还原:
public static Properties loadUtf8Properties(InputStream is) throws IOException {
Properties props = new Properties();
String content = new String(is.readAllBytes(), StandardCharsets.UTF_8);
// 将 UTF-8 原始文本按行拆分,跳过注释和空行
BufferedReader br = new BufferedReader(new StringReader(content));
String line;
while ((line = br.readLine()) != null) {
line = line.trim();
if (line.isEmpty() || line.startsWith("#") || line.startsWith("!")) continue;
// 手动处理 key=value 分割(忽略等号在值中的情况)
int sepIdx = line.indexOf('=');
if (sepIdx > 0) {
String key = unescape(line.substring(0, sepIdx).trim());
String value = unescape(line.substring(sepIdx + 1).trim());
props.setProperty(key, value);
}
}
return props;
}
// 简化版 unescape:只处理 \uXXXX 形式(不处理 \t \n 等,如需可扩展)
private static String unescape(String s) {
StringBuilder sb = new StringBuilder();
for (int i = 0; i <p>该方法完全脱离 <code>Properties.load()</code> 的 ISO-8859-1 绑定,字节读取、解码、转义三步清晰分离,可稳定适配任意编码源文件(只需调整 <code>StandardCharsets.*</code>)。</p><h3>避免陷阱的硬性建议</h3>
- 不要用
new Properties().load(new FileInputStream(...))—— 这是乱码源头; - 不依赖
-Dfile.encoding=UTF-8控制Properties.load(InputStream)行为 —— 它对此无效; - 不在 IDE 中把
.properties文件设为 “Transparent native-to-ascii conversion” 后还存为 UTF-8 —— 这会导致双重转义; - 若必须用标准
load(InputStream),唯一办法是提前将 UTF-8 文件用native2ascii -encoding UTF-8转为\uXXXX格式,但这牺牲可读性,不推荐。
不复杂但容易忽略











