Java:Properties与配置文件
每个应用程序通常都有与之相匹配的配置文件。例如,一个配置文件的设置:
//上次最后打开的文件: last_open_file=/data/hello.txt //自动保存文件的时间间隔 auto_save_interval=60
配置文件的特点是,它的K-V一般都是String-String,所以我们可以用Map<String,String>来表示它。
由于配置文件很常用,所以Java集合库提供了一个Properties来表示一组“配置”。Properties本质上是一个HashTable,但我们只需要用到Properties自身关于读写配置的接口。
模块:java.util.Properties
读取配置文件
Java默认配置文件以.properties为后缀,每行以Key=Value表示,以#开头的是注释。
某个典型的配置文件
#setting.properties last_open_file=/data/hello.txt auto_save_interval=60
可以从文件系统读取这个.properties文件:
String f = "setting.properties"; Properties pros = new Properties(); props.load(new java.io.FileInputStream(f)); String filepath=props.getProperty("last_open_file"); String interval=props.getProperty("auto_save_interval","120");
所以,从Properties读取配置文件,一共有三步:
- 创建Properties实例;
- 调用Properties的load()方法读取配置文件;
- 嗲用Properties的getProperty()获取配置。
调用getProperty()获取配置时,如果Key不存在,会返回null。我们还可以提供一个default,当Key不存在时,返回该default。
在load()加载.properties时,可以从classpath读取,因为load(InputStream)接收一个InputStream实例,表示一个字节流,不一定是文字流,也可能是从jar包中读取的资源流:
Properties props = new Properties(); props.load(getClass().getResourceAsStream("/common/setting.properties"));
尝试从内存(即一个字符串)中读取一个字节流:
import java.io.*; import java.util.Properties; public class Main { public static void main(String[] args) { //定义一个只有2行的K-V String settings = "# test" + "\n" + "course=Java" + "\n" + "last_open_date=2019-08-07T12:35:01"; try { ByteArrayInputStream input = new ByteArrayInputStream(settings.getBytes("UTF-8")); Properties props = new Properties(); props.load(input); System.out.println("course: " + props.getProperty("course")); System.out.println("last_open_date: " + props.getProperty("last_open_date")); System.out.println("auto_save: " + props.getProperty("auto_save", "60")); } catch (UnsupportedEncodingException e) { System.out.println(e); } catch (IOException e) { System.out.println(e); } } }
执行结果:
course: Java last_open_date: 2019-08-07T12:35:01 auto_save: 60
由于getBytes()和load()分别会抛出UnsupportedEncodingException、IOException,所以必须用try...catch...语句将之捕获。
如果有多个.properties文件,可以反复调用load()读取,只是后读取的K-V会覆盖已读取的K-V:
Properties props = new Properties(); props.load(getClass().getResourceAsStream("/common/setting.properties")); props.load(new FileInputStream("C:\\conf\\setting.properties"));
上边的代码演示了Properties的一个常用用法:把默认配置文件放在classpath中,然后根据机器环境编写另一个配置文件,覆盖某些默认配置。
Properties设计的目的是存储String类型的K-V,但其实它是从Hashtable派生的,除了getProperty()、setProperty()方法之外,我们不要调用别的从Hashtable继承下来的方法,比如get()、put()。
写入配置文件
通过setProperty()修改Properties实例,可以把配置写入.properties文件,以便下次启动获得最新配置。写入配置文件使用了store()方法:
Properties props = new Properties(); props.setProperty("url","www.liaoxuefeng.com"); props.setProperty("language","Java"); props.store(new FileOutputStream("C:\\conf\\setting.properties"),"这是写入的properties注释");
编码
早期的.properties文件编码是ASCII;从JDK9开始,可以使用UTF-8编码。
需要注意的是,load( InputStream )默认以ASCII编码读取字节流,所以会导致读到乱码。为了解决这个问题,我们需要用另一个重载方法load( Reader )读取:
Properties props = new Properties(); props.load(new FileReader("settings.properties",StandardCharsets.UTF-8));
就可以正常读取中文。InputStream和Reader的区别在于,前者是字节流,后者是字符流。字符流在内存中已经以char类型表示了,不涉及编码。

浙公网安备 33010602011771号