Read Java properties file in C #

** Introduction **

Stack Overflow has a question _ “Can .NET load and parse a properties file equivalent to Java Properties class?” (January, 2009) _ I'm asking how to read the properties file in C #. There are cases, like the questioner, who want to read the existing properties file in C # as is, without making any changes.

There are some coded answers to the question, but none of the implementations are practical, except my answer. .. Some even add specifications that do not exist. Treat ; and ' as comment line start characters, and remove quotes surrounding property values.

After all there is no choice but to make it yourself.

** Properties file specifications **

The Java properties file specification is [java.util.Properties.load (java.io.Reader)](https://docs.oracle.com/javase/9/docs/api/java/util/Properties. It is written in JavaDoc of html # load-java.io.Reader-) </ code>. The problem is that the spec is a bit more complicated than you might imagine. Although not exhaustive, the following points should be considered in particular.

  1. There are two types of lines: natural line and logical line.
  2. Natural lines are separated by \ n, \ r, \ r \ n or at the end of the stream.
  3. A logical line may span multiple adjacent natural lines by escaping the line terminator sequence with a backslash.
  4. The whitespace character group at the beginning of the second and subsequent natural lines in the logical line is discarded.
  5. Whitespace characters are spaces (``, \ u0020), tabs (\ t, \ u0009), and line feeds (\ f, \ u000C).
  6. As explicitly stated in the specification, _ "When determining if a line terminator is escaped, it is not enough to look at the character before the line terminator sequence, because the line terminator is escaped. Must have a series of odd backslashes. The input is processed from left to right, so there are 2n (non-zero even) backslashes before (or elsewhere) the line terminator. If present, n backslashes are encoded after escaping. "_
  7. = is used as the key / value delimiter.
  8. : Is also used as a key / value delimiter.
  9. The delimiter between the key and the value is optional.
  10. Comment lines have # or ! as the first non-whitespace character. That is, whitespace characters before # and ! are allowed.
  11. Escaping line terminators with a backslash does not allow comment lines to span multiple lines.
  12. As explicitly stated in the specification, =, : and whitespace characters can also be embedded in the key by escaping them with a backslash.
  13. Even line terminators can be included by using the \ r and \ n escase sequences.
  14. If the value is omitted, it is treated as an empty string.
  15. \ uxxxx stands for Unicode character.
  16. Backslashes placed before characters that do not make up a valid escape character are not treated as an error and are simply dropped.

** Examples of Properties file **

That's why, 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 pair group.

Key value
key1 value1
key2 value2
key3 value3
key4 value4
key5 value5
key6 value6
: = \colon\space\equal

** Code example **

NuGet The PropertiesLoader class contained in the package" Authlete.Authlete "is the Properties file. Can interpret the specifications of. The following code example

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}");
            }
        }
    }
}

Produces the following output.

key1 = value1
key2 = value2
key3 = value3
key4 = value4
key5 = value5
key6 = value6
: = = \colon\space\equal

Here's a similar code in Java:

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());
        }    
    }
}

Source code

The source code for PropertiesLoader.cs </ code> is authlete-csharp It exists in (: //github.com/authlete/authlete-csharp). Also, the xUnit test group for PropertiesLoader is [PropertiesLoaderTest.cs](https://github.com/authlete/authlete-csharp/blob/ It is described in master / Authlete.Tests / Util / PropertiesLoaderTest.cs) </ code>.

Recommended Posts