讲解Java Properties

The Java Properties Class java.util.Properties is like a Java Map of Java String key and value pairs. The Java Properties Class can 

write the key, value pairs to a properties file on disk, and read the properties back in again. This is an often used mechanism for storing

simple configuration properties for java applications.

Create a Properties Instance

To use the java Properties class you must first create a Properties instance. You do so via its constructor and the java new instruction.

Here is an example of creating a Java Properties instance:

Properties properties = new Properties();

Set Properties

To set properties in a Java Properties instance you use the setProperty() method. Here is an example of setting a property(key-value pair) in a Java Properties Object:

properties.setProperty("email", "john@doe.com");

This example sets the property with the key mail to the value john@doe.com

Remove Properties

You can remove a property from a Java Properties instance using its remove() method , passing as parameter to remove the key for the property to remove.

Here is an example of removing a property from a Java Properties instance:

properties.remove("email");

Iterate Properties

You can iterate the keys of a Jave Properties instance by obtaining the key set for the Properties instance, and iterating this key set.

Here is an example of obtaining the key set of a Java Properties to iterate all its keys:

public class TestProperties {
    @Test
    public void testProperties01() {
        Properties properties = new Properties();
        properties.setProperty("key1", "value1");
        properties.setProperty("key2", "value2");
        properties.setProperty("key3", "value3");
        properties.setProperty("key4", "value4");

        Iterator<Object> iterator = properties.keySet().iterator();
        while (iterator.hasNext()) {
            String key = (String)iterator.next();
            String value = properties.getProperty(key);

            System.out.println( key + " = " + value);
        }
    }
}

This example will print out the following lines:

key1 = value1
key2 = value2
key3 = value3

Store Properties to File

You can store the property key, value pairs to a properties file which can be read again later on. You store the contents of a Properties Object via its store() method.

Here is an example of storing the contents of a Java Properties to a properties file:

    @Test
    public void testStoreProperties() throws IOException {
        // create Properties Object
        Properties properties = new Properties();

        // set Properties key-value pairs
        properties.setProperty("key1", "value1");
        properties.setProperty("key2", "value2");
        properties.setProperty("key3", "value3");
        properties.setProperty("key4", "value4");

        // write Properties Object to a properties file
        String rootPath = TestProperties.class.getClassLoader().getResource("").getPath();
        File propsFile = new File(rootPath + "data/props.properties");
        try (FileWriter writer = new FileWriter(propsFile)) {
            properties.store(writer, "These are properties");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

Property File Format

A Java Properties property file consists of lines with one key=value pair on each line. Here is an example Java Properties Proerty File:

#These are properties
#Fri Aug 26 23:06:02 CST 2022
key4=value4
key3=value3
key2=value2
key1=value1

The lines starting the # are comments. Notice the first line of the properties file is actually the comment that was passed as second parameter to the store() method call in the code example in the previous section about storing properties to a property file.

The lines following the key=value format contain the property key, value pairs.

Load Properties From File

You can also load properties stored in a property file back into a Java Properties Object via its load() method. 

Here is an example of loading a property file into a Java Properties Object:

    @Test
    public void testLoadProperties() throws Exception {
        Properties properties = new Properties();

        // root path
        String rootPath = TestProperties.class.getClassLoader().getResource("").getPath();
        File file = new File(rootPath + "data/props.properties");
        if (!file.exists()) {
            throw new Exception("The data/props.properties file not exist.");
        }
        try(FileReader reader = new FileReader(file)) {
            properties.load(reader);
        } catch (IOException e) {
            e.printStackTrace();
        }

        properties.keySet().forEach(key -> {
            String value = properties.getProperty((String)key);
            System.out.println(key + " = " + value);
        });
    }

File Encoding When Loading Properties File

By default the load() method will assume that the loaded file is encoded using ISO-8859-1 (Latin-1). If your property file is using another encoding.

 for instance UTF-8, you ,must specify the encoding as the second parameter to the Java FileReader used to load the properties file.

Here is an example of setting file encoding to UTF-8 when loading a Java Properties File:


try(InputStreamReader reader = new InputStreamReader(new FileInputStream(file), StandardCharsets.UTF_8)) {
properties.load(reader);
} catch (Exception e) {
e.printStackTrace();
}

Store Properties to XML File

The Java Properties class can also write the key-value pairs stored in it to an XML file via its storeXML().

Here is an example of storing a Java Properties to an XML File:

    @Test
    public void testStorePropertiesToXML() throws IOException {
        // create Properties Object
        Properties properties = new Properties();

        // set Properties key-value pairs
        properties.setProperty("key1", "value1");
        properties.setProperty("key2", "value2");
        properties.setProperty("key3", "value3");
        properties.setProperty("key4", "value4");

        // write Properties Object to a properties file
        String rootPath = TestProperties.class.getClassLoader().getResource("").getPath();
        File propsFile = new File(rootPath + "data/props.xml");
        if (!propsFile.exists()) {
            propsFile.createNewFile();
        }

        try(FileOutputStream output = new FileOutputStream(propsFile)){
            properties.storeToXML(output, "These are properties", "UTF-8");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

XML Property File Format

The Java Properties object stored to XML file in the example in the previous section looks like this:

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd">
<properties>
<comment>These are properties</comment>
<entry key="key4">value4</entry>
<entry key="key3">value3</entry>
<entry key="key2">value2</entry>
<entry key="key1">value1</entry>
</properties>

Notice how the comment passed to the storeToXML() method is enclosed in a comment XML element, and not in an XML comment (<!-- -->) .

Load Properties from XML File

You can load properties from an XML property file into a Java Properties Object via its loadFromXML() method. 

Here is an example of loading properties from an XML property file into a Java Properties Object:

    @Test
    public void testLoadPropertiesFromXMLFile() throws Exception {
        Properties properties = new Properties();
        String rootPath = TestProperties.class.getClassLoader().getResource("").getPath();
        File xmlFile = new File(rootPath + "data/props.xml");
        if (!xmlFile.exists()) {
            throw new Exception("the xml properties file not exist!");
        }
        try (InputStream inputStream = new FileInputStream(xmlFile)) {
            properties.loadFromXML(inputStream);
        } catch (Exception e) {
            e.printStackTrace();
        }

        properties.keySet().forEach(key -> {
            String value = properties.getProperty((String)key);
            System.out.println( key + " = " + value);
        });
    }

File Encoding When Loading XML Properties Files

By default the loadFromXML() method will assume that the XML file is stored using the UTF-8 encoding. Note, that this is the reverse of the defaults for non-xml property

file. If you XML file is using a different encoding, e.g ISO-8859-1(Latin-1), then your XML file must specify the encoding inside it.

This is done by including the following line as the very first line of your XML properties file:

<?xml version="1.0" encoding="ISO-8859-1"?>

Load Properties From the Classpath

It is possible to load properties into a Java Properties from a file that is available on the classpath. That file could thus be located inside the same JAR file as 

the application loading the properties or inside another JAR file or directory available on the java classpath when your java application is executed.

To load properties form a file available on the classpath, you need to obtain a class instance first. In the example below, I obtain it from the class that contains the

main() method of my application:

Class aClass = PropertiesExample.class;

Once I have the class instance, I can call its getResourceAsStream() method which returns a Java InputSteam referencing the  Properties file. 

Here is an example of obtaining a reference to a file from the classpath:

InputStream inputStream =
    aClass.getResourceAsStream("/myProperties.properties");

The file would have to be located in the root directory of the classpath. If you put it into a subdirectory, the path passed to getResourceAsStream() should refect that.

e.g /subdir/myProperties.properties.

Using the InputStream you can load file into a java Properties instance, using either the load() or loadFromXML() methods explained earlier in this java Properties turorial.

which method to use depends on the format used by the propert file. Here is an example of loading the properties via load():

Class aClass = PropertiesExample.class;

InputStream inputStream =
    aClass.getResourceAsStream("/myProperties.properties");

Properties fromClasspath = new Properties();

try {
    fromClasspath.load(inputStream);
} catch (IOException e) {
    e.printStackTrace();
}

ResourceBundle Properties

Java contains a special type of Properties called a ResouceBundle. A ResouceBundle is a bundle of files that together make up a bundle.

typically, each file will contain a set of properties specifically targeted for a specific language. Thus, each file will typically contain the same

set of property keys, but with values that are specific to the language targeted by that file. ResourceBundle property file are typically loaded from the classpath.

ResouceBundle are common way to internationalize your application. I have covered internationalization of Java applications in my Java Internationalization tutorial.

the Link: https://jenkov.com/tutorials/java-internationalization/index.html

The ResourceBundle class is covered as part of that tutorial, in the Java ResourceBundle tutorial.

the link: https://jenkov.com/tutorials/java-internationalization/resourcebundle.html

Default Properties

The Java Properties class has the ability to provide default property values for properties that do not have any key registered in the Properties instance.

There are two ways of using default proporty values. These are:

  • Provide a default value to the getProperty() method.
  • Provide a Properties instance containing default values when creating a new Properties instance.

The following sections will show example of both of these ways of providing default values for properties.

Default Values With getProperty()

The getProperty() comes in a version that takes an extra parameter which is the default value to return in case the Properties instance does not contain a value 

for the given key. Here is an example of calling getProperty() with a default value.

Properties properties = new Properties();
String preferredLanguage =
    properties.getProperty("preferredLanguage", "Danish");

If the Properties instance does not contain a property for the key preferredLanguage,  then the value Danish will be returned. -instead of returning null 

which would have been returned if no default value had been passed to getProperty().

Default Values With a Default Properties Instance

The Java Properties class can be instantiated with another Properties instance containing default values to use when the newly created Properties instance does not contain a value for a requested property key. Here is an example of instantiating a Properties instance with another Properties instance for providing default values:

Properties defaultProperties = new Properties();
defaultProperties.setProperty("preferredLanguage", "Danish");

Properties newProperties = new Properties(defaultProperties);
String language = newProperties.getProperty("preferredLanguage");

System.out.println("Preferred language: " + language);

Since we did not set any property value for the key preferredLanguage in the newProperties instance, the newProperties instance will look in the defaultProperties for a value instead.

System Properties

The System Properties in Java is a special Properties instance containing system specific properties. These System Properties are setting VM etc.

You can access the Java System Properties via the System.getProperties() method. Here is an example of getting the Java System Properties:

Properties systemProperties = System.getProperties();

You can now get and set System specific properties via this properties instance.

The System class also has a getProperty() and setProperty() method which are shortcuts to the Properties getProperty() and setProperty() methods of the System 

Properties instance. Here is an example of calling System.getProperty() and System.setProperty():

System.setProperty("key1", "value1");
String value1 = System.getProperty("key1");

//The above is equal to:

Properties systemProperties = System.getProperties();

systemProperties.setProperty("key1", "value1");
String value1 = systemProperties.getProperty("key1");

Setting Java System Properties via the Command Line

You can set Java System property keys and values when you startup your Java application, via the Java command on the command line. You can do so via -D argument.

Here is an example of setting Java System Properties via the command line:

java -Dkey1=value1 -cp . com.jenkov.MyApp

This command tells Java to execute the class com.jenkov.MyApp, using currently directory as classpath, and setting the System property named key1 to value value1.

System properties that are set on the command line are also available at runtime via System Properties. You should access the above key1 property inside your applicatoin,

like this:

String key1Property = System.getProperty("key1");

Properties is a Subclass of Hashtable - by Mistake!

The Java Properties class is subclass of the Java Hashtable class, and as I will show you - this is actually a design mistake! 

It is a great example of when the classic "Is a / Has a" OOP rule about when to use inheritance vs composition fails. Let's see how.

Being a subclass of Hashtable, you can actually use the get() and put() method of Hashtable class, which allow the use of non-string keys and values.

This defeats the purpose of the Properties class, which is to function as string, string map. 

Here is an example of using put() on Properties:

Properties asProperties = new Properties();

asProperties.put(123, 456);
asProperties.put("abc", 999);

Notice how it is possible to call put() with non-string keys.

Just to make it clear: You should NOT use the put() and get() method of Properties class!

Using these methods can lead to unpredictable resluts. Look at this example:

Properties asProperties = new Properties();

asProperties.put("abc", 999);

String abc = asProperties.getProperty("abc");
System.out.println(abc);

The getProperty("abc") call will actually return null !!

If instead the value passed to put() had been two strings, then it would have worked as expected. Look at this example:

Properties asProperties = new Properties();

asProperties.put("abc", "999");

String abc = asProperties.getProperty("abc");
System.out.println(abc);

Notice how the second value passed to put() is now also a string. Now the getProperty("abc") call actually returns the string 999.

Even if you can get get() and put() to work, I would recommend that you do not use these methods. Stick to setProperty() and getProperty() methods.

As mentioned earlier, this is an example of the "Is a / Has a" gone wrong. A Java Properties instance clearly is as Hashtable, but it should not share the Hashtable interface. So - the "Is a" part of this rule should be interpreted as "Should be usable as a" instead. Using that formulation, Properties would not have been made a subclass of Hashtable, because Properties should not be usable as a Hashtable .

Instead, the Properties class should have just had an internal Hashtable to keep the property key,value pairs in.

转载自:https://jenkov.com/tutorials/java-collections/properties.html

posted @ 2022-08-27 11:51  fjxszx_hss  阅读(28)  评论(0)    收藏  举报