Java的Properties类并非只能处理.properties文件,JDK 1.5起还提供了一套XML格式的读写能力。借助loadFromXML和storeToXML两个方法,开发者可以让配置以XML形式存储,从而解决传统properties文件里中文必须转义、注释能力弱的问题。不过这套XML有固定结构,不是任意XML都能直接读取。本文围绕格式要求、加载步骤、写出方式以及常见错误展开,给出可以直接运行的示例。

先来说明Properties认可的XML格式。它由java.util.Properties内部约定,核心是根元素、entry节点和key属性,文件头部还需要一条DOCTYPE声明。理解这些约束后,加载和写出就很容易掌握。
一、Properties能读取的XML格式规范
Properties类能够读取的XML并不是随意编写的配置文件,它必须遵循一套固定的DTD。文档根节点固定为<properties>,每一项配置使用<entry>节点表示。键名不允许放在文本内容里,而是必须写在entry节点的key属性上;键对应的值放在entry节点的文本内容中。文件开头还需要通过DOCTYPE声明指向Properties定义的DTD,这样解析器才能识别这种结构。
下面是一个合法的XML配置文件示例,它包含应用名称、数据库地址和数据库用户名三个配置项。
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd">
<properties>
<comment>应用基础配置</comment>
<entry key="app.name">订单中心</entry>
<entry key="db.url">jdbc:mysql://localhost:3306/order_db</entry>
<entry key="db.user">root</entry>
</properties>
这里需要留意,每个entry的key属性必须存在,否则加载时会抛出异常。节点内的文本可以包含中文、空格和大部分特殊字符,不需要像.properties文件那样把中文写成Unicode转义,这是XML格式最直接的好处。根节点下还可以放置<comment>节点,用来承载整份配置的说明,之后调用写出方法时注释也会一并保存。
另外,XML配置天然支持Unicode,编码由XML声明部分指定。也就是说,文件里写的是UTF-8,解析时就会按UTF-8处理,不必再担心ISO-8859-1默认字符集导致的中文乱码问题。对于需要多人维护、需要阅读注释的配置场景,这种格式明显更友好。
二、用loadFromXML方法完成加载
加载XML配置的核心方法是loadFromXML(InputStream in)。它的使用方式与load方法类似,传入一个输入流即可。方法内部会按照Properties规定的XML结构解析文档,并把所有entry节点转换成键值对存入Properties对象。如果XML格式不正确,会抛出InvalidPropertiesFormatException,它是IOException的子类。
实际项目中,配置通常放在类路径下,比如Maven工程的src/main/resources目录。下面这段代码演示了从类路径读取config.xml并获取属性值的完整流程。
import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;
public class LoadXmlConfig {
public static void main(String[] args) {
Properties props = new Properties();
// 使用try-with-resources确保输入流被关闭
try (InputStream in = LoadXmlConfig.class.getClassLoader()
.getResourceAsStream("config.xml")) {
if (in == null) {
System.out.println("未找到配置文件 config.xml");
return;
}
props.loadFromXML(in);
String appName = props.getProperty("app.name");
String dbUrl = props.getProperty("db.url");
String dbUser = props.getProperty("db.user");
System.out.println("应用名称: " + appName);
System.out.println("数据库地址: " + dbUrl);
System.out.println("数据库用户: " + dbUser);
} catch (IOException e) {
System.err.println("加载XML配置失败: " + e.getMessage());
e.printStackTrace();
}
}
}
代码中使用了try-with-resources语法,JVM会在代码块执行结束后自动关闭输入流,避免手动调用close的遗漏。读取类路径资源时,getResourceAsStream返回的流可能为null,例如文件名写错或者资源没有被打包进classpath,所以加载前做了空值判断。这个判断在实际项目中很有必要,否则会触发NullPointerException而不是更明确的文件缺失提示。
加载完成后,获取配置值的方式与普通properties文件完全一致,依然使用getProperty方法。也就是说,XML只是存储形态变了,Properties对象的使用习惯没有改变。如果之后想切换回.properties格式,代码中读取属性的部分几乎不需要调整,只需要替换加载方法为load即可。
三、将Properties对象写出为XML文件
除了读取,Properties还可以把内存中的键值对写回XML文件,对应的方法是storeToXML(OutputStream os, String comment, String encoding)。第一个参数是输出流,第二个参数是写入XML的注释,第三个参数指定字符编码,通常写成UTF-8。如果使用只带输出流和注释的重载方法,编码会默认使用UTF-8。
下面示例先创建一个Properties对象,放入几项配置,然后将其存储为XML文件。
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Properties;
public class StoreXmlConfig {
public static void main(String[] args) {
Properties props = new Properties();
props.setProperty("server.host", "127.0.0.1");
props.setProperty("server.port", "8080");
props.setProperty("server.timeout", "30");
try (OutputStream out = new FileOutputStream("server-config.xml")) {
props.storeToXML(out, "服务端基础配置", "UTF-8");
System.out.println("XML配置已写出");
} catch (IOException e) {
System.err.println("写出XML配置失败: " + e.getMessage());
e.printStackTrace();
}
}
}
执行后生成的XML文件会带有注释节点,内容类似下面这样,所有键值对都转换成entry节点。
<?xml version="1.0" encoding="UTF-8" standalone="no"?> <!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd"> <properties> <comment>服务端基础配置</comment> <entry key="server.host">127.0.0.1</entry> <entry key="server.port">8080</entry> <entry key="server.timeout">30</entry> </properties>
写入时使用UTF-8编码可以保证中文注释和中文配置值不出现乱码。需要特别注意的是,storeToXML默认会写入XML声明和DOCTYPE声明,这些信息在下次加载时必须保持完整,否则会读不回来。输出流同样要记得关闭,示例中借助try-with-resources处理了文件输出流。
四、加载XML时容易踩到的坑
最常见的错误是XML根节点名称写错或者漏掉DOCTYPE声明。例如有人直接把根节点写成<config>,或者只写第一行XML声明而不写DOCTYPE,这时调用loadFromXML会直接抛出InvalidPropertiesFormatException,提示内容通常是找不到properties元素或者文档格式不合法。排查时先检查根节点是否是<properties>,再确认DOCTYPE是否存在。
另一个容易忽略的问题是entry节点的key属性。手工编辑XML时,可能会写出没有key属性的entry节点,例如<entry>value</entry>。这种结构在Properties的XML规范中是非法的,加载时同样会失败。正确写法必须是<entry key="键名">值</entry>,键名不能为空,值可以是空文本,但key属性不能省略。
还有一点是文件包含特殊字符。XML本身对<、>、&等字符敏感,如果在配置值中出现这些字符,需要按照XML规则转义。比如数据库密码包含&,应写成&。不过这一层通常由XML解析器处理,手工编辑时容易忘记,如果加载报错,可以优先检查这些特殊符号。
关于DOCTYPE中的DTD地址,标准写法指向http://java.sun.com/dtd/properties.dtd。在JDK的默认实现中,加载通常不会因为网络不可用而失败,但在某些安全加固或离线环境中,外部DTD访问可能被限制。如果遇到异常,可以先确认运行环境是否允许外部资源访问,必要时将配置改为使用本地DTD副本。对于大部分内部配置读取场景,保留标准DOCTYPE即可。
最后是格式选择问题。如果配置项不多、没有中文注释需求,继续使用.properties文件完全够用,它的加载速度更快,文件也更小。如果配置需要跨系统交换、需要良好的可读性、需要保存注释或者值中包含大量中文,XML配置是更合适的选择。Properties类的XML读写能力让两种格式切换成本很低,可以按实际项目情况灵活决定。
Java PropertiesloadFromXMLXML配置文件修改时间:2026-10-06 07:07:41