properties.load()默认iso-8859-1解码致中文乱码,应使用inputstreamreader指定utf-8;store()不保证顺序且线程不安全,需用linkedhashmap或concurrenthashmap替代;spring boot中优先用@configurationproperties而非手动读写。

Properties.load() 读取配置时中文乱码怎么办
Java 的 Properties 默认用 ISO-8859-1 解码,读取含中文的配置文件(如 UTF-8 编码的 app.properties)会显示为问号或方块。这不是文件损坏,是编码不匹配。
- 最稳妥做法:改用
InputStreamReader指定 UTF-8,再传给load(),例如:try (InputStream is = Files.newInputStream(Paths.get("app.properties")); Reader reader = new InputStreamReader(is, StandardCharsets.UTF_8)) { props.load(reader); } - 别依赖 IDE 自动保存为 UTF-8 就万事大吉——Windows 记事本另存为 UTF-8 会带 BOM,
Properties无法跳过,导致首行 key 解析失败 - 如果必须用默认
load(InputStream),就得提前把中文转成 Unicode 转义(如name=\u4f60\u597d),但维护成本高,不推荐
Properties.store() 写入后配置项顺序混乱
Properties 继承自 Hashtable,内部无序;JDK 1.8+ 虽在 store() 中按字母序输出 key,但这是副作用,不是保证行为。你不能靠它维持“数据库配置在前、日志配置在后”的排版。
- 若需固定顺序,改用
LinkedHashMap+ 手动拼接字符串写入,或引入第三方库如 Apache Commons Configuration -
store()生成的注释行(#开头)和空行会被忽略,不要指望用空行分隔模块 - 调用
store()前没调用setProperty()或直接操作put(),可能导致部分键值未写入——put()插入的是 Object 类型,store()只序列化 String 类型的键值对
在 Spring Boot 里还该手写 Properties 读写吗
不该。Spring Boot 的 @ConfigurationProperties 和 @Value 已封装好类型安全、校验、环境隔离等能力,硬套原生 Properties 反而绕路。
- 直接用
ResourceLoader加载classpath:xxx.properties再 parse,等于放弃 Spring 的配置绑定机制和 profile 支持 - 如果只是临时读一个外部配置文件(比如运维给的独立
secret.properties),可用Properties+Resource,但记得加异常兜底——文件不存在或权限不足时load()抛IOException,别让它崩掉整个启动流程 -
System.getProperties()和System.getenv()是只读快照,修改它们不影响运行时行为,也别试图拿它们当配置中心用
Properties 线程安全吗?并发读写会出什么问题
不安全。Properties 方法本身没加锁,多个线程同时 setProperty() 和 store() 可能导致写入内容错乱、部分 key 丢失,甚至 ConcurrentModificationException。
立即学习“Java免费学习笔记(深入)”;
- 读多写少场景:用
Collections.synchronizedMap(new Properties())包一层,但注意entrySet().iterator()这类复合操作仍需手动同步 - 写操作频繁(比如动态刷新配置),建议换成
ConcurrentHashMap<string string></string>,自己管理持久化逻辑,别被Properties的历史包袱绑住 - 别在静态块里初始化全局
Properties实例并供多处修改——看似方便,实则埋下竞态雷
真正麻烦的从来不是读写动作本身,而是默认编码、隐式类型转换、以及你以为它有序/线程安全的错觉。










