Yet another answer (in January 2018) to the old question (in January 2009).
The specification of Java properties file is described in the JavaDoc of java.util.Properties.load(java.io.Reader)
. One problem is that the specification is a bit complicated than the first impression we may have. Another problem is that some answers here arbitrarily added extra specifications - for example, ;
and '
are regarded as starters of comment lines but they should not be. Double/single quotations around property values are removed but they should not be.
The following are points to be considered.
- There are two kinds of line, natural lines and logical lines.
- A natural line is terminated by
\n
, \r
, \r\n
or the end of the stream.
- A logical line may be spread out across several adjacent natural lines by escaping the line terminator sequence with a backslash character
\
.
- Any white space at the start of the second and following natural lines in a logical line are discarded.
- White spaces are space (
, \u0020
), tab (\t
, \u0009
) and form feed (\f
, \u000C
).
- As stated explicitly in the specification, "it is not sufficient to only examine the character preceding a line terminator sequence to decide if the line terminator is escaped; there must be an odd number of contiguous backslashes for the line terminator to be escaped. Since the input is processed from left to right, a non-zero even number of 2n contiguous backslashes before a line terminator (or elsewhere) encodes n backslashes after escape processing."
=
is used as the separator between a key and a value.
:
is used as the separator between a key and a value, too.
- The separator between a key and a value can be omitted.
- A comment line has
#
or !
as its first non-white space characters, meaning leading white spaces before #
or !
are allowed.
- A comment line cannot be extended to next natural lines even its line terminator is preceded by
\
.
- As stated explicitly in the specification,
=
, :
and white spaces can be embedded in a key if they are escaped by backslashes.
- Even line terminator characters can be included using
\r
and \n
escape sequences.
- If a value is omitted, an empty string is used as a value.
\uxxxx
is used to represent a Unicode character.
- A backslash character before a non-valid escape character is not treated as an error; it is silently dropped.
So, for example, if test.properties
has the following content:
# A comment line that starts with '#'.
# This is a comment line having leading white spaces.
! A comment line that starts with '!'.
key1=value1
key2 : value2
key3 value3
key\
4=value\
4
\u006B\u0065\u00795=\u0076\u0061\u006c\u0075\u00655
\k\e\y\6=\v\a\lu\e\6
\:\ \= = \\colon\\space\\equal
it should be interpreted as the following key-value pairs.
+------+--------------------+
| KEY | VALUE |
+------+--------------------+
| key1 | value1 |
| key2 | value2 |
| key3 | value3 |
| key4 | value4 |
| key5 | value5 |
| key6 | value6 |
| : = | \colon\space\equal |
+------+--------------------+
PropertiesLoader
class in Authlete.Authlete NuGet package can interpret the format of the specification. The example code below:
using System;
using System.IO;
using System.Collections.Generic;
using Authlete.Util;
namespace MyApp
{
class Program
{
public static void Main(string[] args)
{
string file = "test.properties";
IDictionary<string, string> properties;
using (TextReader reader = new StreamReader(file))
{
properties = PropertiesLoader.Load(reader);
}
foreach (var entry in properties)
{
Console.WriteLine($"{entry.Key} = {entry.Value}");
}
}
}
}
will generate this output:
key1 = value1
key2 = value2
key3 = value3
key4 = value4
key5 = value5
key6 = value6
: = = \colon\space\equal
An equivalent example in Java is as follows:
import java.util.*;
import java.io.*;
public class Program
{
public static void main(String[] args) throws IOException
{
String file = "test.properties";
Properties properties = new Properties();
try (Reader reader = new FileReader(file))
{
properties.load(reader);
}
for (Map.Entry<Object, Object> entry : properties.entrySet())
{
System.out.format("%s = %s\n", entry.getKey(), entry.getValue());
}
}
}
The source code, PropertiesLoader.cs
, can be found in authlete-csharp. xUnit tests for PropertiesLoader
are written in PropertiesLoaderTest.cs
.