How to overwrite one property in .properties without overwriting the whole file?
Asked Answered
S

9

32

Basically, I have to overwrite a certain property in a .properties file through a Java app, but when I use Properties.setProperty() and Properties.Store() it overwrites the whole file rather than just that one property.

I've tried constructing the FileOutputStream with append = true, but with that it adds another property and doesn't delete/overwrite the existing property.

How can I code it so that setting one property overwrites that specific property, without overwriting the whole file?

Edit: I tried reading the file and adding to it. Here's my updated code:

FileOutputStream out = new FileOutputStream("file.properties");
FileInputStream in = new FileInputStream("file.properties");
Properties props = new Properties();

props.load(in);
in.close();

props.setProperty("somekey", "somevalue");
props.store(out, null);
out.close();
Slag answered 18/9, 2011 at 13:55 Comment(6)
If you read in the properties, add/change a property to that, and write out those properties, all of the properties should be there--can you show the code you tried for that?Estimate
@Dave Newton: Yeah, but they are not in the same order. This is a known problem... I guess this is what OP really wants.Tumbledown
@home: Oh, I get it. Yeah, the curse of unordered collections, I guess. If that's the problem, might as well just treat it as a string, do a replace, and write it back out.Estimate
There, just updated. Still same result, whole file is overwritten.Slag
Another answer reminded me of the Apache Commons Configuration library, specifically the capabilities PropertiesConfigurationLayout. This allows (more or less) the original layout, comments, ordering, etc. to be preserved.Estimate
Possible duplicate of Updating property value in properties file without deleting other valuesFiducial
F
21

The Properties API doesn't provide any methods for adding/replacing/removing a property in the properties file. The model that the API supports is to load all of the properties from a file, make changes to the in-memory Properties object, and then store all of the properties to a file (the same one or a different one).

But the Properties API is not unusual in the respect. In reality, in-place updating of a text file is difficult to implement without rewriting the entire file. This difficulty is a direct consequence of the way that files / file systems are implemented by a modern operating system.

If you really need to do incremental updates, then you need to use some kind of database to hold the properties, not a ".properties" file.


Other Answers have suggested the following approach in various guises:

  1. Load properties from file into Properties object.
  2. Update Properties object.
  3. Save Properties object on top of existing file.

This works for some use-cases. However the load / save is liable to reorder the properties, remove embedded comments and white space. These things may matter1.

The other point is that this involves rewriting the entire properties file, which the OP is explicitly trying2 to avoid.


1 - If the API is used as the designers intended, property order, embedded comments, and so on wouldn't matter. But lets assume that the OP is doing this for "pragmatic reasons".
2 - Not that it is practical to avoid this; see earlier.

Freewheeling answered 18/9, 2011 at 14:36 Comment(0)
P
19

You can use PropertiesConfiguration from Apache Commons Configuration.

In version 1.X:

PropertiesConfiguration config = new PropertiesConfiguration("file.properties");
config.setProperty("somekey", "somevalue");
config.save();

From version 2.0:

Parameters params = new Parameters();
FileBasedConfigurationBuilder<FileBasedConfiguration> builder =
    new FileBasedConfigurationBuilder<FileBasedConfiguration>(PropertiesConfiguration.class)
    .configure(params.properties()
        .setFileName("file.properties"));
Configuration config = builder.getConfiguration();
config.setProperty("somekey", "somevalue");
builder.save();
Poplar answered 20/3, 2013 at 11:27 Comment(4)
This is the best solution. It keeps the properties file intact; doesn't mess it up.Microstructure
You need to change: props.setProperty --> config.setPropertyMacmacabre
While this is a pragmatic solution, it is not what the OP asked for. Specifically, the entire file is being rewritten / overwritten.Freewheeling
As of version 2.1.1 save() method and the constructor you are using is not supported . Have you any alternatives :) ?Jacoby
P
2

I know this is an old question, but this is working code (slightly modified from the code in the question, to prevent the deletion of the values before we load them):

FileInputStream in = new FileInputStream("file.properties");
Properties props = new Properties();

props.load(in);
in.close();

props.setProperty("somekey", "somevalue");

FileOutputStream out = new FileOutputStream("file.properties");
props.store(out, null);
out.close();
Precautionary answered 9/5, 2023 at 8:47 Comment(2)
This is indeed the correct answer. You must open up the FileOutputStream after you close the FileInputStream, otherwise the instance of the file opened will be overwritten.Codfish
To write in UTF-8: props.store(new OutputStreamWriter(new FileOutputStream("file.properties"), "UTF-8"), null);Algonquian
H
1

Properties files are an easy way to provide configuration for an application, but not necessarily a good way to do programmatic, user-specific customization, for just the reason that you've found.

For that, I'd use the Preferences API.

Hippy answered 18/9, 2011 at 14:43 Comment(0)
A
1

I do the following method:-

  1. Read the file and load the properties object
  2. Update or add new properties by using ".setProperty" method. (setProperty method is better than .put method as it can be used for inserting as well as updating the property object)
  3. Write the property object back to file to keep the file in sync with the change.
Anadem answered 4/10, 2016 at 6:33 Comment(0)
I
0
public class PropertiesXMLExample {
    public static void main(String[] args) throws IOException {

    // get properties object
    Properties props = new Properties();

    // get path of the file that you want
    String filepath = System.getProperty("user.home")
            + System.getProperty("file.separator") +"email-configuration.xml";

    // get file object
    File file = new File(filepath);

    // check whether the file exists
    if (file.exists()) {
        // get inpustream of the file
        InputStream is = new FileInputStream(filepath);

        // load the xml file into properties format
        props.loadFromXML(is);

        // store all the property keys in a set 
        Set<String> names = props.stringPropertyNames();

        // iterate over all the property names
        for (Iterator<String> i = names.iterator(); i.hasNext();) {
            // store each propertyname that you get
            String propname = i.next();

            // set all the properties (since these properties are not automatically stored when you update the file). All these properties will be rewritten. You also set some new value for the property names that you read
            props.setProperty(propname, props.getProperty(propname));
        }

        // add some new properties to the props object
        props.setProperty("email.support", "[email protected]");
        props.setProperty("email.support_2", "[email protected]");

       // get outputstream object to for storing the properties into the same xml file that you read
        OutputStream os = new FileOutputStream(
                System.getProperty("user.home")
                        + "/email-configuration.xml");

        // store the properties detail into a pre-defined XML file
        props.storeToXML(os, "Support Email", "UTF-8");

        // an earlier stored property
        String email = props.getProperty("email.support_1");

        System.out.println(email);
      }
   }
}

The output of the program would be:

[email protected]
Incensory answered 25/6, 2013 at 2:49 Comment(0)
I
0

Please use just update file line instead using Properies e.g.

public static void updateProperty(String key, String oldValue, String newValue)
{
    File f = new File(CONFIG_FILE);
    try {
        List<String> fileContent = new ArrayList<>(Files.readAllLines(f.toPath(), StandardCharsets.UTF_8));

        for (int i = 0; i < fileContent.size(); i++) {
            if (fileContent.get(i).replaceAll("\\s+","").equals(key + "=" + oldValue)) {
                fileContent.set(i, key + " = " + newValue);
                break;
            }
        }
        Files.write(f.toPath(), fileContent, StandardCharsets.UTF_8);
    } catch (Exception e) {
        
    }
}
Ivory answered 8/2, 2022 at 16:34 Comment(0)
S
-1
import java.io.*;
import java.util.*;

class WritePropertiesFile
{

             public static void main(String[] args) {
        try {
            Properties p = new Properties();
            p.setProperty("1", "one");
            p.setProperty("2", "two");
            p.setProperty("3", "three");

            File file = new File("task.properties");
            FileOutputStream fOut = new FileOutputStream(file);
            p.store(fOut, "Favorite Things");
            fOut.close();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
Seismograph answered 14/3, 2013 at 21:38 Comment(0)
F
-1

If you just want to override 1 prop why not just add parameter to your java command. Whatever you provide in your properties file they will be overrided with properties args.

java -Dyour.prop.to.be.overrided="value" -jar  your.jar
Faucher answered 16/7, 2020 at 10:15 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.