Java Properties简介

212 阅读5分钟
原文链接: www.ripjava.com

1. 概述

大多数Java应用程序需要在某些时候使用属性,通常我们是在编译代码之外将参数存储为键值对。

在Java SE API里有对属性的支持 。java.util.Properties是为处理此类配置文件而设计的实用程序类。这就是我们将在本文中关注的内容。

2.加载属性

2.1 从属性文件加载

让我们从一个用于从属性文件加载键值对开始。

加载在类路径上可用的两个文件:

app.properties:

version=1.0
name=TestApp
date=2019-07-02

catalog:

c1=files
c2=images
c3=videos

虽然建议属性文件使用*.properties*后缀,但这并不是必需的。

我们可以很简单地将属性加载到Properties实例中:

 @Test
    public  void test_loadProperties() throws IOException {
        String rootPath = "src/test/resources/";
        String appConfigPath = rootPath + "app.properties";
        String catalogConfigPath = rootPath + "catalog";

        Properties appProps = new Properties();
        appProps.load(new FileInputStream(appConfigPath));

        Properties catalogProps = new Properties();
        catalogProps.load(new FileInputStream(catalogConfigPath));


        String appVersion = appProps.getProperty("version");
        assertEquals("1.0", appVersion);

        assertEquals("files", catalogProps.getProperty("c1"));
    }

只要文件的内容符合属性文件格式要求,就可以通过Properties类正确解析。

这里是属性文件格式的更多详细信息。

2.2. 从XML文件加载

除了属性文件,Properties类还可以加载符合特定DTD规范的XML文件。

以下是从XML文件加载键值对的示例

icons.xml

<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd">
<properties>
    <comment>xml example</comment>
    <entry key="fileIcon">icon1.jpg</entry>
    <entry key="imageIcon">icon2.jpg</entry>
    <entry key="videoIcon">icon3.jpg</entry>
</properties>

现在,让我们加载它:

    @Test
    public  void test_loadXML() throws IOException {
        String rootPath = "src/test/resources/";
        String iconConfigPath = rootPath + "icons.xml";
        Properties iconProps = new Properties();
        iconProps.loadFromXML(new FileInputStream(iconConfigPath));

        assertEquals("icon1.jpg", iconProps.getProperty("fileIcon"));
    }

3.获取属性

我们可以使用*getProperty(String key)getProperty(String key,String defaultValue)*来获取其键的值。

如果键值对存在,则两个方法都将返回相应的值。但是如果没有这样的键值对,前者将返回null,而后者将返回defaultValue

测试代码:

    @Test
    public  void test_getProperty() throws IOException {
        String rootPath = "src/test/resources/";
        String appConfigPath = rootPath + "app.properties";
        Properties appProps = new Properties();
        appProps.load(new FileInputStream(appConfigPath));
        String appVersion = appProps.getProperty("version");
        String appName = appProps.getProperty("name", "defaultName");
        String appGroup = appProps.getProperty("group", "defaultGroup");
        String appDownloadAddr = appProps.getProperty("downloadAddr");

        assertEquals("1.0", appVersion);
        assertEquals("TestApp", appName);
        assertEquals("defaultGroup", appGroup);
        assertNull(appDownloadAddr);
    }

需要注意的是:Properties类从Hashtable类继承了*get()*方法,但不建议您使用它来获取值。

因为它的get()方法将返回一个Object值,该值只能转换为String

getProperty()方法已经为我们将原始Object值转换为String了。

下面的代码将抛出异常

float appVerFloat = (float) appProps.get("version");

4.设置属性

我们可以使用*setProperty()*方法更新现有的键值对或添加新的键值对。

测试代码:

    @Test
    public  void test_setProperty() throws IOException {
        String rootPath = "src/test/resources/";
        String appConfigPath = rootPath + "app.properties";
        Properties appProps = new Properties();
        appProps.load(new FileInputStream(appConfigPath));

        appProps.setProperty("name", "NewAppName");
        appProps.setProperty("downloadAddr", "xxxx");

        String newAppName = appProps.getProperty("name");
        assertEquals("NewAppName", newAppName);

        String newAppDownloadAddr = appProps.getProperty("downloadAddr");
        assertEquals("xxxx", newAppDownloadAddr);

        appProps.put("version", 2);
        String version = appProps.getProperty("version");
        assertNull(version);

    }

虽然Properties类从Hashtable类继承了*put()方法和putAll()*方法,但还是不建议使用它们, 原因和get()方法相同。

下面的代码将无法正常工作,当使用getProperty()获取其值时,它将返回null:

appProps.put("version", 2);

5.删除属性

如果要删除键值对,可以使用*remove()*方法。

测试代码:

    @Test
    public  void test_remove() throws IOException {
        String rootPath = "src/test/resources/";
        String appConfigPath = rootPath + "app.properties";
        Properties appProps = new Properties();
        appProps.load(new FileInputStream(appConfigPath));
        String versionBeforeRemoval = appProps.getProperty("version");
        assertEquals("1.0", versionBeforeRemoval);

        appProps.remove("version");
        String versionAfterRemoval = appProps.getProperty("version");
        assertNull(versionAfterRemoval);
    }

6.存储

6.1. 存储到属性文件

Properties类提供了一个*store()*方法来输出键值对。

测试代码:

    @Test
    public  void test_storeProperties() throws IOException {
        String rootPath = "src/test/resources/";
        String newAppConfigPropertiesFile = rootPath + "newApp.properties";
        Properties appProps = new Properties();
        appProps.setProperty("name", "NewAppName");
        appProps.setProperty("download", "downloadUrl");
        appProps.store(new FileWriter(newAppConfigPropertiesFile), "store to properties file");

        Properties newAppProps = new Properties();
        newAppProps.load(new FileInputStream(newAppConfigPropertiesFile));
        String newAppName = newAppProps.getProperty("name");
        assertEquals("NewAppName", newAppName);

        String newAppDownload = newAppProps.getProperty("download");
        assertEquals("downloadUrl", newAppDownload);

    }

生成的文件内容如下

#store to properties file
#Tue Jul 02 22:28:18 JST 2019
download=downloadUrl
name=NewAppName

第二个参数用于添加注释的。如果您不想写任何注释,只需使用null即可。

6.2. 存储到XML文件

Properties类还提供*storeToXML()*方法,以XML格式输出键值对。

    @Test
    public  void test_storeXML() throws IOException {
        String rootPath = "src/test/resources/";
        String newAppConfigXmlFile = rootPath + "newApp.xml";

        Properties appProps = new Properties();
        appProps.setProperty("name", "NewAppName");
        appProps.setProperty("download", "downloadUrl");
        appProps.storeToXML(new FileOutputStream(newAppConfigXmlFile), "store to xml file");

        Properties newAppProps = new Properties();
        newAppProps.loadFromXML(new FileInputStream(newAppConfigXmlFile));
        String newAppName = newAppProps.getProperty("name");
        assertEquals("NewAppName", newAppName);

        String newAppDownload = newAppProps.getProperty("download");
        assertEquals("downloadUrl", newAppDownload);
    }

生成的文件内容如下:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd">
<properties>
<comment>store to xml file</comment>
<entry key="download">downloadUrl</entry>
<entry key="name">NewAppName</entry>
</properties>

第二个参数与*store()*方法中的参数相同。

7.其他方法

Properties类还提供了一些其他方法来操作属性。

示例代码:

    @Test
    public  void test_otherMethod() throws IOException {
        String rootPath = "src/test/resources/";
        String newAppConfigPropertiesFile = rootPath + "newApp.properties";

        Properties appProps = new Properties();
        appProps.load(new FileInputStream(newAppConfigPropertiesFile));

        appProps.list(System.out);

        Enumeration<Object> valueEnumeration = appProps.elements();
        while (valueEnumeration.hasMoreElements()) {
            System.out.println(valueEnumeration.nextElement());
        }

        Enumeration<Object> keyEnumeration = appProps.keys();
        while (keyEnumeration.hasMoreElements()) {
            System.out.println(keyEnumeration.nextElement());
        }

        int size = appProps.size();
        assertEquals(2, size);

    }

输出如下:

download=downloadUrl
name=NewAppName
downloadUrl
NewAppName
download
name

8.默认属性列表

一个属性对象可以包含另一个属性对象作为其默认的属性列表。 如果在原始属性键中找不到属性键,则将搜索默认属性列表。

除了“ app.properties ”之外, 我们在类路径上还有另一个文件“ default.properties ”:

default.properties:

site=www.google.com
name=DefaultAppName
topic=Properties
category=core-java

测试代码

@Test
    public  void test_defaultPropertiesObject() throws IOException {
        String rootPath = "src/test/resources/";
        String defaultConfigPath = rootPath + "default.properties";
        Properties defaultProps = new Properties();
        defaultProps.load(new FileInputStream(defaultConfigPath));

        String appConfigPath = rootPath + "app.properties";
        // 设置默认的属性列表
        Properties appProps = new Properties(defaultProps);
        appProps.load(new FileInputStream(appConfigPath));

        String appVersion = appProps.getProperty("version");
        assertEquals("1.0", appVersion);
        String appName = appProps.getProperty("name");
        assertEquals("TestApp", appName);
        String defaultSite = appProps.getProperty("site");
        assertEquals("www.google.com", defaultSite);
    }

9.结论

在本文中,我们讨论了基本的Properties类用法,包括:

  • 如何在Properties和XML格式中使用Properties加载和存储键值对
  • 如何在Properties对象中操作键值对,例如检索值,更新值,获取其大小
  • 如何使用Properties对象的默认列表

最后,往常一样,代码可以在Github上找到。