Skip to content
On this page

Properties File

When writing applications, it is often necessary to read and write configuration files. For example, user settings:

# Last opened file:
last_open_file=/data/hello.txt
# Auto-save interval in seconds:
auto_save_interval=60

The characteristic of configuration files is that their key-value pairs are generally of type String-String, so we can represent them using Map<String, String>.

Since configuration files are very common, the Java Collections Framework provides a Properties class to represent a set of "configurations." Due to historical reasons, Properties is essentially a Hashtable, but we only need to use the Properties interface for reading and writing configurations.

Reading Configuration Files

Reading a configuration file with Properties is very simple. The default extension for configuration files in Java is .properties, with each line represented as key=value and lines starting with # being comments. Here is a typical configuration file:

# setting.properties

last_open_file=/data/hello.txt
auto_save_interval=60

This .properties file can be read from the file system as follows:

java
String f = "setting.properties";
Properties props = new Properties();
props.load(new java.io.FileInputStream(f));

String filepath = props.getProperty("last_open_file");
String interval = props.getProperty("auto_save_interval", "120");

As we can see, there are three steps to read a configuration file using Properties:

  1. Create a Properties instance.
  2. Call load() to read the file.
  3. Call getProperty() to retrieve the configuration.

When calling getProperty(), if the key does not exist, it will return null. We can also provide a default value, which will be returned when the key does not exist.

You can also read .properties files from the classpath, as the load(InputStream) method accepts an InputStream, which can be a byte stream that is not necessarily a file stream, but could also be a resource stream read from a JAR file:

java
Properties props = new Properties();
props.load(getClass().getResourceAsStream("/common/setting.properties"));

Let's try reading a byte stream from memory:

java
// properties
import java.io.*;
import java.util.Properties;

public class Main {
    public static void main(String[] args) throws IOException {
        String settings = "# test" + "\n" + "course=Java" + "\n" + "last_open_date=2019-08-07T12:35:01";
        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("last_open_file: " + props.getProperty("last_open_file"));
        System.out.println("auto_save: " + props.getProperty("auto_save", "60"));
    }
}

If there are multiple .properties files, you can repeatedly call load() to read them, with later loaded key-value pairs overwriting earlier ones:

java
Properties props = new Properties();
props.load(getClass().getResourceAsStream("/common/setting.properties"));
props.load(new FileInputStream("C:\\conf\\setting.properties"));

The code above demonstrates a common use case of Properties: you can place a default configuration file in the classpath and then create another configuration file based on the machine environment to override some of the default configurations.

The design of Properties is intended to store String type key-value pairs. However, Properties is derived from Hashtable, which has design issues. To maintain compatibility, it cannot be modified now. In addition to getProperty() and setProperty() methods, there are also get() and put() methods inherited from Hashtable, which take Object as parameters. When using Properties, avoid calling these methods inherited from Hashtable.

Writing Configuration Files

If you modify a Properties instance using setProperty(), you can write the configuration back to a file so that the latest configuration is available the next time the application starts. Use the store() method to write to a configuration file:

java
Properties props = new Properties();
props.setProperty("url", "http://www.liaoxuefeng.com");
props.setProperty("language", "Java");
props.store(new FileOutputStream("C:\\conf\\setting.properties"), "This is a properties comment");

Encoding

Early versions of Java specified that .properties files must be encoded in ASCII (ISO8859-1). If Chinese characters are involved, they must be represented as name=\u4e2d\u6587, which is very awkward. Since JDK 9, .properties files can now use UTF-8 encoding.

However, it is important to note that since load(InputStream) always reads byte streams using ASCII encoding by default, this can lead to garbled text. We need to use another overloaded method load(Reader) for reading:

java
Properties props = new Properties();
props.load(new FileReader("settings.properties", StandardCharsets.UTF_8));

This will allow you to read Chinese characters correctly. The difference between InputStream and Reader is that one is a byte stream and the other is a character stream. The character stream represents data as char in memory, which avoids encoding issues.

Summary

The Properties class provided by the Java Collections Framework is used to read and write .properties configuration files, which can use UTF-8 encoding.

You can read .properties files from the file system, classpath, or any other location.

When reading and writing Properties, be sure to only use getProperty() and setProperty() methods, and avoid calling inherited methods like get() and put().

Properties File has loaded