Properties类按顺序输出加载内容
程序员文章站
2022-04-14 15:43:22
Properties类按顺序输出加载内容 最近手写工厂的时候,遇到了加载配置文件时不按照properties文件中的数据的顺序来加载。 一、问题代码 配置文件 输出结果 二、原因分析 上面是Properties类的定义,可以看到它继承了Hashtable类 load方法调用load0方法 方法: H ......
properties类按顺序输出加载内容
最近手写工厂的时候,遇到了加载配置文件时不按照properties文件中的数据的顺序来加载。
一、问题代码
import java.io.ioexception; import java.io.inputstream; import java.util.properties; public class propertiestest { public static void main(string[] args) { inputstream ips = null; try { ips = properties.class.getresourceasstream("/test.properities"); properties props = new properties(); props.load(ips); for(string name:props.stringpropertynames()) system.out.println(props.getproperty(name) + " "+name); } catch (ioexception e) { e.printstacktrace(); }finally { try { if(ips != null){ ips.close(); } } catch (ioexception e) { e.printstacktrace(); } } } }
配置文件
cat=1 dog=2 bird=3 mouse=4 pig=5
输出结果
二、原因分析
public class properties extends hashtable<object,object>
上面是properties类的定义,可以看到它继承了hashtable类
public synchronized void load(inputstream instream) throws ioexception { load0(new linereader(instream)); }
load方法调用load0方法
private void load0 (linereader lr) throws ioexception { char[] convtbuf = new char[1024]; int limit; int keylen; int valuestart; char c; boolean hassep; boolean precedingbackslash; while ((limit = lr.readline()) >= 0) { c = 0; keylen = 0; valuestart = limit; hassep = false; //system.out.println("line=<" + new string(linebuf, 0, limit) + ">"); precedingbackslash = false; while (keylen < limit) { c = lr.linebuf[keylen]; //need check if escaped. if ((c == '=' || c == ':') && !precedingbackslash) { valuestart = keylen + 1; hassep = true; break; } else if ((c == ' ' || c == '\t' || c == '\f') && !precedingbackslash) { valuestart = keylen + 1; break; } if (c == '\\') { precedingbackslash = !precedingbackslash; } else { precedingbackslash = false; } keylen++; } while (valuestart < limit) { c = lr.linebuf[valuestart]; if (c != ' ' && c != '\t' && c != '\f') { if (!hassep && (c == '=' || c == ':')) { hassep = true; } else { break; } } valuestart++; } string key = loadconvert(lr.linebuf, 0, keylen, convtbuf); string value = loadconvert(lr.linebuf, valuestart, limit - valuestart, convtbuf); put(key, value); } }
load0方法可以看到最后取到key和value值后会调用父类hashtable的put()
方法,把数据存入hashtable,具体的hashtable源码这里就不再贴出。简单来说hashtable的put()
方法接收到值后会按照哈希值存储,而不是按照读取顺序存储。
接下来是读取时的源码,有兴趣的可以看一下:
public set<string> stringpropertynames() { hashtable<string, string> h = new hashtable<>(); enumeratestringproperties(h); return h.keyset(); }
enumeratestringproperties
方法:
private synchronized void enumeratestringproperties(hashtable<string, string> h) { if (defaults != null) { defaults.enumeratestringproperties(h); } for (enumeration<?> e = keys() ; e.hasmoreelements() ;) { object k = e.nextelement(); object v = get(k); if (k instanceof string && v instanceof string) { h.put((string) k, (string) v); } } }
hashtable的keyset()
方法
public set<k> keyset() { if (keyset == null) keyset = collections.synchronizedset(new keyset(), this); return keyset; }
三、解决方法
写一个工具类继承properties类,实现以下功能:
- 创建一个能够按照读取顺序来存储properities文件中的key值的集合框架
- 能够返回步骤1创建的集合
在这里我采用了linkedlist
来顺序存储key值(也可以采用别的集合类型),然后重写put方法,先把值存入自己建的linkedlist
中,再调用父类的方法。关于返回key值的集合是新写了一个orderstringpropertynames()
方法返回linkedlist
实现代码如下:
import java.util.linkedlist; import java.util.properties; public class linkedproperities extends properties { private linkedlist<string> linkedlist = new linkedlist<string>(); @override public synchronized object put(object key, object value) { linkedlist.add((string) key); return super.put(key, value); } public linkedlist<string> orderstringpropertynames() { return linkedlist; } }