42

Though java.util.properties allows reading and writing properties file, the writing does not preserve the formatting. Not surprising, because it is not tied to the property file.

Is there a PropertyFile class out there -- or some such -- that preserves comments and blank lines and updates property values in place?

Shubham
  • 2,847
  • 4
  • 24
  • 37
Miserable Variable
  • 28,432
  • 15
  • 72
  • 133

8 Answers8

63

It doesn't get much better than Apache's Commons Configuration API. This provides a unified approach to configuration from Property files, XML, JNDI, JDBC datasources, etc.

It's handling of property files is very good. It allows you to generate a PropertiesConfigurationLayout object from your property which preserves as much information about your property file as possible (whitespaces, comments etc). When you save changes to the property file, these will be preserved as best as possible.


Sample code:

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStreamReader;

import org.apache.commons.configuration.ConfigurationException;
import org.apache.commons.configuration.PropertiesConfiguration;
import org.apache.commons.configuration.PropertiesConfigurationLayout;

public class PropertiesReader {
    public static void main(String args[]) throws ConfigurationException, FileNotFoundException {
        File file = new File(args[0] + ".properties");

        PropertiesConfiguration config = new PropertiesConfiguration();
        PropertiesConfigurationLayout layout = new PropertiesConfigurationLayout(config);
        layout.load(new InputStreamReader(new FileInputStream(file)));

        config.setProperty("test", "testValue");
        layout.save(new FileWriter("path\\to\\properties\\file.properties", false));
    }
}

See also:

iamkenos
  • 1,446
  • 8
  • 24
  • 49
Il-Bhima
  • 10,744
  • 1
  • 47
  • 51
  • 1
    That works great and keeps the comments there. Took the liberty to add some sample code :) – Patrick Boos Jan 06 '15 at 14:40
  • 7
    The supplied code doesn't compile .. propsFile is not declared – blank Apr 09 '15 at 13:02
  • What if you have a key value like Spring.Names = cookie@!jar@!johnson@!james@!green@!patrick. How would you add "Jimmy" after patrick? – JayC Dec 12 '16 at 18:50
11

The sample code for using the Apache Commons Configuration library contributed by Patrick Boos is unnecessarily complicated. You don't need to use PropertiesConfigurationLayout explicitly unless you require some advanced control over the output. PropertiesConfiguration by itself is sufficient to preserve comments and formatting:

PropertiesConfiguration config = new PropertiesConfiguration("myprops.properties");
config.setProperty("Foo", "Bar");
config.save();

(Note: This code works for the existing 1.10 stable version. I have not checked if it works on the 2.0 alpha builds currently available.)

John Rix
  • 6,271
  • 5
  • 40
  • 46
  • This worked. But the issue is that, we are getting one space after "=" in key=value pair, which is unwanted. Because I have value with doesnot need space. Eg: test=xyz is value in properties file. But after running the above code, I am getting test = xyz. I dont need space before 'xyz' – Jince Martin Sep 26 '16 at 10:44
  • 1
    It doesn't work with Version 2.1.1 , these methods except setProperty doesn't exist. I am very curious though to know why they removed such elegant methods , like `save()` ... :( – GOXR3PLUS May 12 '17 at 07:50
7

The configuration2 class have different syntax. Here is an example using them:

import org.apache.commons.configuration2.PropertiesConfiguration;
import org.apache.commons.configuration2.PropertiesConfigurationLayout;

public void test() {
    PropertiesConfiguration config = new PropertiesConfiguration();
    PropertiesConfigurationLayout layout = new PropertiesConfigurationLayout();
    config.setLayout(layout);
    layout.load(config, new FileReader("config.properties"));

    config.setProperty("KEY", "VALUE");
    StringWriter stringWriter = new StringWriter();
    layout.save(config, stringWriter);
    LOG.debug("Properties:\n{}", stringWriter.toString());
}
Kevin Le
  • 71
  • 1
  • 4
7

You can have a look to the Apache Commons Configuration, that contains PropertiesConfiguration class. However, as I have never used it, I don't know if it preserves the comments and formatting...

However, it worthes a try...

Romain Linsolas
  • 79,475
  • 49
  • 202
  • 273
1
    File file = new File("src/test/resources/1automation.properties");
    PropertiesConfiguration config = new PropertiesConfiguration();
    PropertiesConfigurationLayout layout = new PropertiesConfigurationLayout(config);
    layout.load(new InputStreamReader(new FileInputStream(file)));
    FileWriter fw = new FileWriter("src/test/resources/1automation.properties",false);
    config.setProperty("myssi.admin.name", "testValue");
    layout.save(fw);
  • 1
    This worked. But the issue is that, we are getting one space after "=" in key=value pair, which is unwanted. Because I have value with doesnot need space. Eg: test=xyz is value in properties file. But after running the above code, I am getting test = xyz. I dont need space before 'xyz' – Jince Martin Sep 26 '16 at 10:33
  • My comment might be a bit too late, but you can always use `trim()` to remove unwanted spaces. – Rahul Jawale Nov 14 '17 at 18:15
0

The best answer contains a small mistake: The line:

PropertiesConfigurationLayout layout = new PropertiesConfigurationLayout(config);

Must be replaced by:

PropertiesConfigurationLayout layout = config.getLayout();
Jeremy
  • 1
0

Just in response to Jince Martin who was having trouble with trailing spaces in the written properties files e.g. key = value instead of key=value.

You can call layout.setGlobalSeparator("=") to get around this.

-1

I once saw a class to do this with INI files but can't find the link anymore. If you can't find anything else, you can try DecentXML. I wrote this XML parser with the specific design goal to preserve the original formatting 100% (i.e. with comments, weird spaces in elements or around the root element, everything).

During parsing the resulting XML document, you just have to remember the elements which contain the value for your options and replace the text node in them. When you save, nothing untouched will change in any way.

Aaron Digulla
  • 321,842
  • 108
  • 597
  • 820