Reputation: 53806
This is custom java properties file which preserves insertion order of the elements. When I run the below code the properties are not written to file. The contents of the file is just :
#Mon Dec 02 13:39:55 GMT 2013
Do I need to override another method ? Shouldn't this work since the custom properties file is extending the main Properties file so all methods which are not overridden should behave the same way ?
No exceptions are thrown
The code :
package com.test;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.util.Date;
import java.util.Enumeration;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
public class LinkedProperties extends Properties{
private static final long serialVersionUID = 1L;
private Map<Object, Object> linkMap = new LinkedHashMap<Object,Object>();
@Override
public synchronized Object put(Object key, Object value){
return linkMap.put(key, value);
}
@Override
public synchronized boolean contains(Object value){
return linkMap.containsValue(value);
}
@Override
public boolean containsValue(Object value){
return linkMap.containsValue(value);
}
@Override
public synchronized Enumeration<Object> elements(){
throw new UnsupportedOperationException(
"Enumerations are so old-school, don't use them, "
+ "use keySet() or entrySet() instead");
}
@Override
public Set<java.util.Map.Entry<Object, Object>> entrySet(){
return linkMap.entrySet();
}
@Override
public synchronized void clear(){
linkMap.clear();
}
@Override
public synchronized boolean containsKey(Object key){
return linkMap.containsKey(key);
}
@Override
public synchronized Object setProperty(String key, String value) {
return put(key, value);
}
}
package com.test;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
public class Runner {
public static void main(String args[]){
LinkedProperties l = new LinkedProperties();
l.put("test", "test");
try {
l.store(new FileOutputStream("c:/text.txt"),null);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
Update :
Thanks to the answers provided by raphw & frostjogla I am now using this custom class to write the properties in order :
package com.test;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.util.Date;
import java.util.Enumeration;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
public class LinkedProperties extends Properties {
private static final long serialVersionUID = 1L;
private Map<Object, Object> linkMap = new LinkedHashMap<Object, Object>();
@Override
public synchronized Object put(Object key, Object value) {
return linkMap.put(key, value);
}
@Override
public synchronized boolean contains(Object value) {
return linkMap.containsValue(value);
}
@Override
public boolean containsValue(Object value) {
return linkMap.containsValue(value);
}
@Override
public synchronized Enumeration<Object> elements() {
throw new UnsupportedOperationException(
"Enumerations are so old-school, don't use them, "
+ "use keySet() or entrySet() instead");
}
@Override
public Set<java.util.Map.Entry<Object, Object>> entrySet() {
return linkMap.entrySet();
}
@Override
public synchronized void clear() {
linkMap.clear();
}
@Override
public synchronized boolean containsKey(Object key) {
return linkMap.containsKey(key);
}
@Override
public synchronized Object setProperty(String key, String value) {
return put(key, value);
}
public synchronized void store(OutputStream out, String comments)
throws IOException {
BufferedWriter awriter;
awriter = new BufferedWriter(new OutputStreamWriter(out, "8859_1"));
if (comments != null)
writeln(awriter, "#" + comments);
writeln(awriter, "#" + new Date().toString());
for (Iterator<java.util.Map.Entry<Object, Object>> e = linkMap.entrySet().iterator(); e.hasNext();) {
java.util.Map.Entry<Object, Object> entry = (java.util.Map.Entry<Object, Object>) e.next();
String key = (String) entry.getKey();
String val = (String) entry.getValue();
key = saveConvert(key, true);
/*
* No need to escape embedded and trailing spaces for value, hence
* pass false to flag.
*/
val = saveConvert(val, false);
writeln(awriter, key + "=" + val);
}
awriter.flush();
}
private static void writeln(BufferedWriter bw, String s) throws IOException {
bw.write(s);
bw.newLine();
}
private String saveConvert(String theString, boolean escapeSpace) {
int len = theString.length();
int bufLen = len * 2;
if (bufLen < 0) {
bufLen = Integer.MAX_VALUE;
}
StringBuffer outBuffer = new StringBuffer(bufLen);
for (int x = 0; x < len; x++) {
char aChar = theString.charAt(x);
// Handle common case first, selecting largest block that
// avoids the specials below
if ((aChar > 61) && (aChar < 127)) {
if (aChar == '\\') {
outBuffer.append('\\');
outBuffer.append('\\');
continue;
}
outBuffer.append(aChar);
continue;
}
switch (aChar) {
case ' ':
if (x == 0 || escapeSpace)
outBuffer.append('\\');
outBuffer.append(' ');
break;
case '\t':
outBuffer.append('\\');
outBuffer.append('t');
break;
case '\n':
outBuffer.append('\\');
outBuffer.append('n');
break;
case '\r':
outBuffer.append('\\');
outBuffer.append('r');
break;
case '\f':
outBuffer.append('\\');
outBuffer.append('f');
break;
case '=': // Fall through
case ':': // Fall through
case '#': // Fall through
case '!':
outBuffer.append('\\');
outBuffer.append(aChar);
break;
default:
if ((aChar < 0x0020) || (aChar > 0x007e)) {
outBuffer.append('\\');
outBuffer.append('u');
outBuffer.append(toHex((aChar >> 12) & 0xF));
outBuffer.append(toHex((aChar >> 8) & 0xF));
outBuffer.append(toHex((aChar >> 4) & 0xF));
outBuffer.append(toHex(aChar & 0xF));
} else {
outBuffer.append(aChar);
}
}
}
return outBuffer.toString();
}
private static char toHex(int nibble) {
return hexDigit[(nibble & 0xF)];
}
/** A table of hex digits */
private static final char[] hexDigit = { '0', '1', '2', '3', '4', '5', '6',
'7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
}
Upvotes: 0
Views: 2377
Reputation: 43997
If you are looking at the implementation of Properties
, you can find the answer in the store
method which is responsible for writing the properties to the output stream. Here is an excerpt:
bw.write("#" + new Date().toString());
bw.newLine();
for (Enumeration e = keys(); e.hasMoreElements();) { // Here things go wrong!
String key = (String)e.nextElement();
String val = (String)get(key);
key = saveConvert(key, true, escUnicode);
val = saveConvert(val, false, escUnicode);
bw.write(key + "=" + val);
bw.newLine();
}
From this method, you can learn what functionality you need to provide in order to have your properties written to the output file. Internally, Properties
calls the keys
method which is defined in Properties
's super class Hashtable
and which you do not override. Because you are intercepting all methods that fill up the original collection for a Properties
object which is defined in Hashtable
, this collection remains empty. Therefore, keys
which still points to this old, empty collection returns an empty set and you cannot find any output than that of the first line of the above code snippet.
Upvotes: 1
Reputation: 4608
You should override method keys
.
It is original method:
public synchronized Enumeration<K> keys() {
return this.<K>getEnumeration(KEYS);
}
Attach JDK-sources to your IDE for debug application.
Upvotes: 1