Properties files
Properties files are a popular mean of configuring applications. Of course Commons Configuration
supports this format and enhances significantly the basic Using PropertiesConfiguration
Let's start with a simple properties file named
# Properties definining the GUI colors.background = #FFFFFF colors.foreground = #000080 window.width = 500 window.height = 300 To load this file, you'll write: Configuration config = new PropertiesConfiguration("usergui.properties"); If you do not specify an absolute path, the file will be searched automatically in the following locations:
Instead of using a constructor that takes a file name you can also
invoke one of the
After the properties file was loaded you can access its content through
the methods of the String backColor = config.getString("colors.background"); Dimension size = new Dimension(config.getInt("window.width"), config.getInt("window.height")); Includes
If a property is named " # usergui.properties include = colors.properties include = sizes.properties # colors.properties colors.background = #FFFFFF Lists and arraysAs was already pointed out in the section List handling of Basic features, Commons Configuration has the ability to return easily a list of values. For example a properties file can contain a list of comma separated values: # chart colors colors.pie = #FF0000, #00FF00, #0000FF
You don't have to split the value manually, you can retrieve an array
or a String[] colors = config.getStringArray("colors.pie"); List<Object> colorList = config.getList("colors.pie"); Alternatively, you can specify a list of values in your properties file by using the same key on several lines: # chart colors colors.pie = #FF0000; colors.pie = #00FF00; colors.pie = #0000FF;
All of the features related to list handling described for
Saving
To save your configuration, just call the PropertiesConfiguration config = new PropertiesConfiguration("usergui.properties"); config.setProperty("colors.background", "#000000"); config.save(); You can also save a copy of the configuration to another file: PropertiesConfiguration config = new PropertiesConfiguration("usergui.properties"); config.setProperty("colors.background", "#000000"); config.save("usergui.backup.properties); More information about saving properties files (and file-based configurations in general) can be found in the section about File-based Configurations. Special Characters and EscapingIf you need a special character in a property like a line feed, a tabulation or an unicode character, you can specify it with the same escaped notation used for Java Strings. The list separator ("," by default), can also be escaped: key = This \n string \t contains \, escaped \\ characters \u0020 When dealing with lists of elements that contain backslash characters (e.g. file paths on Windows systems) escaping rules can become pretty complex. The first thing to keep in mind is that in order to get a single backslash, you have to write two: config.dir = C:\\Temp\\
This issue is not specific to Commons Configuration, but is related to
the standard format for properties files. Refer to the Javadocs of the
# Wrong way to define a list of directories config.dirs = C:\\Temp\\,D:\\data\\ As the comment indicates, this will not work. The trailing backslash of the first directory is interpreted as escape character for the list delimiter. So instead of a list with two elements only a single value of the property is defined - clearly not what was desired. To get a correct list the trailing backslash has to be escaped. This is achieved by duplicating it (yes, in a properties file that means that we now need 4 backslashes): # Correct way to define a list of directories config.dirs = C:\\Temp\\\\,D:\\data\\ So a sequence of 4 backslashes in the value of a property is interpreted as an escaped backslash and eventually results in a single backslash. This creates another problem when a properties file should refer to the names of network shares. Typically these names start with two backslashes, so the obvious way to define such a property is as follows: # Wrong way to define a list of network shares config.dirs = \\\\share1,\\\\share2 Unfortunately, this will not work because the shares contain the reserved sequence of 4 backslashes. So when reading the value of the config.dirs property a list with two elements is returned starting only with a single backslash. To fix the problem the sequence for escaping a backslash has to be duplicated - we are now at 8 backslashes: # Correct way to define a list of network shares config.dirs = \\\\\\\\share1,\\\\\\\\share2 As becomes obvious, escape sequences can become pretty complex and unreadable. In such situations it is recommended to use the alternative way of defining a list: just use the same key multiple times. In this case no additional escaping of backslashes (beyond the usual duplicating required by properties files) is needed because there is no list delimiter character involved. Using this syntax the list of network shares looks like the following: # Straightforward way to define a list of network shares config.dirs = \\\\share1 config.dirs = \\\\share2 Layout Objects
Each Normally a developer does not have to deal with these layout objects. However, there are some methods that might be of interest if enhanced control over the output of properties files is needed. The following list describes these methods (note that corresponding get methods are of course also provided):
PropertiesConfigurationLayout are
chosen in a way that most of the original layout of a properties file
is retained. With the methods listed above specific layout restrictions
can be enforced.
Custom properties readers and writers
There are situations when more control over the process of reading and
writing properties file is needed. For instance, an application might
have to deal with some legacy properties file in a specific format,
which is not supported out of the box by
Per default properties files are read and written by the nested classes
For installing a custom properties reader or writer
The Background Color = #800080 Foreground Color = #000080
The first step is to create a custom properties reader implementation
that can deal with such properties. The class is derived from
public class WhitespacePropertiesReader extends PropertiesConfiguration.PropertiesReader { public WhitespacePropertiesReader(Reader in, char delimiter) { super(in, delimiter); } /** * Special algorithm for parsing properties keys with whitespace. This * method is called for each non-comment line read from the properties * file. */ protected void parseProperty(String line) { // simply split the line at the first '=' character // (this should be more robust in production code) int pos = line.indexOf('='); String key = line.substring(0, pos).trim(); String value = line.substring(pos + 1).trim(); // now store the key and the value of the property initPropertyName(key); initPropertyValue(value); } }
Notice the calls to the methods public class WhitespaceIOFactory extends PropertiesConfiguration.DefaultIOFactory { /** * Return our special properties reader. */ public PropertiesReader createPropertiesReader(Reader in, char delimiter) { return new WhitespacePropertiesReader(in, delimiter); } }
Finally an instance of our new PropertiesConfiguration config = new PropertiesConfiguration(); config.setIOFactory(new WhitespaceIOFactory()); config.setFile(...); // set the file to be loaded config.load(); |