4

Today I try to store an Object using java.util.properties. I see many example just use String or Integer. Here is an example:

public static void main(String[] args) {
    Properties prop = new Properties();

    // add some properties
    prop.setProperty("Height", "200");
    prop.put("Width", "1500");

    // print the list 
    System.out.println("" + prop);
    try {
        // store the properties list in an output stream
        prop.store(System.out, "config.properties");
    } catch (IOException ex) {
        ex.printStackTrace();
    }
}

So is it possible to store an Object in properties file or xml file?

Nicolas Filotto
  • 43,537
  • 11
  • 94
  • 122
thangdc94
  • 1,542
  • 2
  • 26
  • 38

2 Answers2

4

To store an object at first you should serialize it to a byte array then encode it with a Base64 encoder:

public static String toString(Object o) throws IOException {
    try (ByteArrayOutputStream baos = new ByteArrayOutputStream();
            ObjectOutputStream oos = new ObjectOutputStream(baos);) {
        oos.writeObject(o);
        return new String(Base64Coder.encode(baos.toByteArray()));
    }
}

Then you can store it safely to the property file:

prop.put("object.instance", toString(o));

To read the object from the properties, use this function:

public static Object fromString(String s) throws IOException, ClassNotFoundException {
    byte[] data = Base64Coder.decode(s);
    Object o;
    try (ObjectInputStream ois = new ObjectInputStream(
            new ByteArrayInputStream(data))) {
        o = ois.readObject();
    }
    return o;
}

You can deserialize the object from the string:

Object o = fromString(prop.get("object.instance"));
Community
  • 1
  • 1
JHead
  • 356
  • 2
  • 12
  • Thanks. I will try this. – thangdc94 Jun 13 '16 at 18:07
  • 3
    this is clearly a very bad approach because what you will have in your properties file won't be readable if someone adds a small character in the middle, you are dead – Nicolas Filotto Jun 13 '16 at 18:22
  • @Nicolas Filotto it is not a problem, you can add some error handling that handles the unreadable values and returns null if the serialized object is cracked by the user. Any other properties can be messed up by the user. You can not eliminate it. I think this is one of the best approach. – JHead Jun 13 '16 at 18:50
  • @NicolasFilotto Should I write object into a XML file? Object is just config information. No need to secure. – thangdc94 Jun 13 '16 at 18:50
  • 1
    @JHead and how can you can recover once corrupted? As I said you are dead – Nicolas Filotto Jun 13 '16 at 18:52
  • @NgocThangPham XML or properties file, it doesn't really matter as you prefer XML is only more verbose – Nicolas Filotto Jun 13 '16 at 18:55
  • @Nicolas Filotto you are right, you can not recover. If you need recovery, use XML. Most of the cases there is no need to recover, e.g. view config info. Corrupted string or integer values can't be recovered too. – JHead Jun 13 '16 at 19:00
  • 4
    @NicolasFilotto How do you recover if the user deletes the entire properties file? If the file is writable and the user corrupts it, the user corrupts it. The format doesn't matter at that point. – Andrew Henle Jun 13 '16 at 19:02
  • @AndrewHenle you don't get the point here, what I mean is the fact that it is more doable to recover from an error in something readable,for example if you see pool.size=1ab7 it is easier to fix than pool.size=MabTc= don't you agree? – Nicolas Filotto Jun 13 '16 at 19:08
  • This is a great approach. Thank you! – Matthew Jan 13 '21 at 20:08
2

No as it is stated into the Javadoc:

If the store or save method is called on a "compromised" Properties object that contains a non-String key or value, the call will fail.

If you really need to store your object into a Properties you could convert it into JSON as it is a well known format that is readable by a human being such that if someone adds wrong characters in the middle you can still fix it.

Here is how you could do it using ObjectMapper:

Properties prop = new Properties();

ObjectMapper mapper = new ObjectMapper();
// Convert my object foo into JSON format and put it into my Properties object
prop.put("myObj",  mapper.writeValueAsString(foo));

StringWriter output = new StringWriter();
// Store my properties
prop.store(output, null);

prop = new Properties();
// Load my properties
prop.load(new StringReader(output.toString()));

// Parse my object foo from the value of my new Properties object
Foo foo2 = mapper.readValue(prop.getProperty("myObj"), Foo.class);

Here is a good tutorial that explains how you can use ObjectMapper in more details.

Nicolas Filotto
  • 43,537
  • 11
  • 94
  • 122