Pulling values from a Java Properties file in order?
Solution 1
If you can alter the property names your could prefix them with a numeral or other sortable prefix and then sort the Properties KeySet.
Solution 2
Extend java.util.Properties
, override both put()
and keys()
:
import java.util.Collections;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.Properties;
import java.util.HashMap;
public class LinkedProperties extends Properties {
private final HashSet<Object> keys = new LinkedHashSet<Object>();
public LinkedProperties() {
}
public Iterable<Object> orderedKeys() {
return Collections.list(keys());
}
public Enumeration<Object> keys() {
return Collections.<Object>enumeration(keys);
}
public Object put(Object key, Object value) {
keys.add(key);
return super.put(key, value);
}
}
Solution 3
Nope - maps are inherently "unordered".
You could possibly create your own subclass of Properties
which overrode setProperty
and possibly put
, but it would probably get very implementation-specific... Properties
is a prime example of bad encapsulation. When I last wrote an extended version (about 10 years ago!) it ended up being hideous and definitely sensitive to the implementation details of Properties
.
Solution 4
Working example :
Map<String,String> properties = getOrderedProperties(new FileInputStream(new File("./a.properties")));
properties.entrySet().forEach(System.out::println);
Code for it
public Map<String, String> getOrderedProperties(InputStream in) throws IOException{
Map<String, String> mp = new LinkedHashMap<>();
(new Properties(){
public synchronized Object put(Object key, Object value) {
return mp.put((String) key, (String) value);
}
}).load(in);
return mp;
}
Solution 5
Dominique Laurent's solution above works great for me. I also added the following method override:
public Set<String> stringPropertyNames() {
Set<String> set = new LinkedHashSet<String>();
for (Object key : this.keys) {
set.add((String)key);
}
return set;
}
Probably not the most efficient, but it's only executed once in my servlet lifecycle.
Thanks Dominique!
Comments
-
James McMahon almost 4 years
I have a properties file where the order of the values is important. I want to be able to iterate through the properties file and output the values based on the order of the original file.
However, since the Properties file is backed by, correct me if I'm wrong, a Map that does not maintain insertion order, the iterator returns the values in the wrong order.
Here is the code I'm using
Enumeration names = propfile.propertyNames(); while (names.hasMoreElements()) { String name = (String) names.nextElement(); //do stuff }
Is there anyway to get the Properties back in order short of writting my own custom file parser?
-
James McMahon over 14 yearsI was afraid of that. I'm looking at the Properties code right now and I see exactly what you mean. The backing implementation should really should be a settable delegate. Can you recommend any alternatives? Like would the Apache Commons configuration help me out?
-
James McMahon over 14 yearsJust a quick correction, Java does have a implementation of Map, LinkedHashMap, that DOES maintain insertion order.
-
Jon Skeet over 14 years@nemo: Yes, but that's a map specifically designed for that. Maps in general aren't ordered. I believe Spring has its own properties file reader which you might find useful.
-
James McMahon over 14 yearsYes, that had occurred to me. That might be the simplest workaround.
-
james over 14 yearsextend Properties, override put() and store the keys in an internal List. use said list to iterate the properties in order.
-
James McMahon over 14 yearsThis is actually what I ended up doing. I was only dealing with four values and commons configuration need too many dependencies which would have complicated my build.
-
James McMahon over 14 yearsThis looks interesting, but the using one piece of the commons requires loading several other pieces. I ended up going with a quick and dirty solution.
-
Emmanuel Bourg over 12 yearsMost of the dependencies are optional. For a simple PropertiesConfiguration you only need Commons Lang and Commons Collections.
-
Jordy Boom almost 12 yearsIt would be safer to create your class as a wrapper around Properties, rather than extending it. Only overriding those methods makes assumptions about how the underlying class works (the assumption that putAll() uses put()), and you could run into situations where your keys set is incorrect.
-
Michael Wyraz over 11 yearsYou should really override remove() and clear() as well - otherwise you'll get NullPointerExceptions on save()! Also you should add synchronized as it is in the parent's methods unless the collection used for the keys is thread safe.
-
mirelon about 10 yearsthe type can be inferred in
return Collections.<Object>enumeration(keys);
, so this is sufficient:return Collections.enumeration(keys);
-
Milson almost 9 years[DataMember(Name = "attribute ID", Order = 0)] private int _attributeID; can't we have such thing in Java
-
javaPhobic over 8 yearsThe problem with this approach is, the original Properties class supports more than just the simple example "test=test2" when loading. For example, data can have "=", you can use escapes for special characters etc. Writing your own class means you have to implement a whole lot more.
-
AlikElzin-kilaka over 7 yearsExplaining the code: The trick is to use Java's
Properties
class, override it's put method and put the key into a data structure that saves the order of insertion. This works becauseProperties
puts the keys/values at the same order it reads them from the file - top->bottom. -
walkeros over 7 years-1 - You assume that the put method is called according to the order of properties in the source file. I think you can not assume that this is guaranteed. If the file was read from bottom to top you will get the properties in reversed order.
-
Jaison Varghese about 6 yearsHowever this method sorts the entries alphabetically and doesn't guarantee insertion order (the order of the original file)
-
Joter about 4 yearsThanks!!!! It resolve my problem to save in same order as it present in the file.