プロパティファイルを読み取り、JavaでPropertiesクラスを生成する必要があります。私は以下を使用してこれを行います:
Properties props = new Properties();
props.load(new FileInputStream(args[0]));
for (Enumeration e = props.propertyNames(); e.hasMoreElements();) {
}
ただし、props.propertyNameによって返されるプロパティは、元のプロパティファイルの順序ではありません。 Propertiesは、昔ながらの、生成されていないハッシュテーブルであることを理解しています。回避策を探しています。何か案が?ありがとうございました!
同様の機能を備えた独自のPropertiesクラスを実装することをお勧めします。すでに指摘したように、Hashtable
を使用しているため、注文を取得することはできません。
www.Java2s.com の例で問題が解決するはずです。
import Java.util.Enumeration;
import Java.util.Properties;
import Java.util.Vector;
/**
* <a href="OrderedProperties.Java.html"><b><i>View Source</i></b></a>
*
* @author Brian Wing Shun Chan
*
*/
public class OrderedProperties extends Properties {
public OrderedProperties() {
super ();
_names = new Vector();
}
public Enumeration propertyNames() {
return _names.elements();
}
public Object put(Object key, Object value) {
if (_names.contains(key)) {
_names.remove(key);
}
_names.add(key);
return super .put(key, value);
}
public Object remove(Object key) {
_names.remove(key);
return super .remove(key);
}
private Vector _names;
}
そして、コードは次のように変更されます。
Properties props = new OrderedProperties();
props.load(new FileInputStream(args[0]));
for (Enumeration e = props.propertyNames(); e.hasMoreElements();) {
}
プロパティを拡張し、すべてのマップメソッドを LinkedHashMap に委任して、順序を保持することができます。次に例を示します(さらにいくつかのメソッドをオーバーライドする必要がある場合があります)。
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<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);
}
}
上記のいずれかに似ていますが、独自の値のリストを維持するオーバーヘッドがありません。私たちがしなければならないのは、キーの個別の順序付きリストを維持し、新しい「keys()」メソッドを提供することだけです。
public class SequencedProperties extends Properties {
private static final long serialVersionUID = -7032434592318855760L;
private List keyList = new ArrayList();
@Override
public synchronized Enumeration keys() {
return Collections.enumeration(keyList);
}
@Override
public synchronized Object put(Object key, Object value) {
if (! containsKey(key)) {
keyList.add(key);
}
return super.put(key, value);
}
@Override
public synchronized Object remove(Object key) {
keyList.remove(key);
return super.remove(key);
}
@Override
public synchronized void putAll(Map values) {
for (Object key : values.keySet()) {
if (! containsKey(key)) {
keyList.add(key);
}
}
super.putAll(values);
}
}
linkedHashMapに基づく完全な実装
import Java.util.*;
import Java.io.*;
/**
* Ordered properties implementation
*/
public class LinkedProperties extends Properties{
private static final long serialVersionUID = 1L;
private Map<Object, Object> linkMap = new LinkedHashMap<Object,Object>();
public void clear(){
linkMap.clear();
}
public boolean contains(Object value){
return linkMap.containsValue(value);
}
public boolean containsKey(Object key){
return linkMap.containsKey(key);
}
public boolean containsValue(Object value){
return linkMap.containsValue(value);
}
public Enumeration elements(){
throw new RuntimeException("Method elements is not supported in LinkedProperties class");
}
public Set entrySet(){
return linkMap.entrySet();
}
public boolean equals(Object o){
return linkMap.equals(o);
}
public Object get(Object key){
return linkMap.get(key);
}
public String getProperty(String key) {
Object oval = get(key); //here the class Properties uses super.get()
if(oval==null)return null;
return (oval instanceof String) ? (String)oval : null; //behavior of standard properties
}
public boolean isEmpty(){
return linkMap.isEmpty();
}
public Enumeration keys(){
Set keys=linkMap.keySet();
return Collections.enumeration(keys);
}
public Set keySet(){
return linkMap.keySet();
}
public void list(PrintStream out) {
this.list(new PrintWriter(out,true));
}
public void list(PrintWriter out) {
out.println("-- listing properties --");
for (Map.Entry e : (Set<Map.Entry>)this.entrySet()){
String key = (String)e.getKey();
String val = (String)e.getValue();
if (val.length() > 40) {
val = val.substring(0, 37) + "...";
}
out.println(key + "=" + val);
}
}
public Object put(Object key, Object value){
return linkMap.put(key, value);
}
public int size(){
return linkMap.size();
}
public Collection values(){
return linkMap.values();
}
//for test purpose only
public static void main(String[] arg)throws Exception{
Properties p0=new Properties();
Properties p1=new LinkedProperties();
p0.put("aaa","111");
p0.put("bbb","222");
p0.put("ccc","333");
p0.put("ddd","444");
p1.put("aaa","111");
p1.put("bbb","222");
p1.put("ccc","333");
p1.put("ddd","444");
System.out.println("\n--"+p0.getClass());
p0.list(System.out);
p0.store(System.out,"comments");
p0.storeToXML(System.out,"comments");
System.out.println(p0.toString());
System.out.println("\n--"+p1.getClass());
p1.list(System.out);
p1.store(System.out,"comments");
p1.storeToXML(System.out,"comments");
System.out.println(p1.toString());
}
}
結果:
--class Java.util.Properties
-- listing properties --
bbb=222
aaa=111
ddd=444
ccc=333
#comments
#Wed Apr 10 08:55:42 EEST 2013
bbb=222
aaa=111
ddd=444
ccc=333
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE properties SYSTEM "http://Java.Sun.com/dtd/properties.dtd">
<properties>
<comment>comments</comment>
<entry key="bbb">222</entry>
<entry key="aaa">111</entry>
<entry key="ddd">444</entry>
<entry key="ccc">333</entry>
</properties>
{bbb=222, aaa=111, ddd=444, ccc=333}
--class groovy.abi.LinkedProperties
-- listing properties --
aaa=111
bbb=222
ccc=333
ddd=444
#comments
#Wed Apr 10 08:55:42 EEST 2013
aaa=111
bbb=222
ccc=333
ddd=444
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE properties SYSTEM "http://Java.Sun.com/dtd/properties.dtd">
<properties>
<comment>comments</comment>
<entry key="aaa">111</entry>
<entry key="bbb">222</entry>
<entry key="ccc">333</entry>
<entry key="ddd">444</entry>
</properties>
{aaa=111, bbb=222, ccc=333, ddd=444}
KeySetの適切な実装:
public class OrderedProperties extends Properties {
private Set<Object> keySet = new LinkedHashSet<Object>(100);
@Override
public Enumeration<Object> keys() {
return Collections.enumeration(keySet);
}
@Override
public Set<Object> keySet() {
return keySet;
}
@Override
public synchronized Object put(Object key, Object value) {
if (! keySet.contains(key)) {
keySet.add(key);
}
return super.put(key, value);
}
@Override
public synchronized Object remove(Object key) {
keySet.remove(key);
return super.remove(key);
}
@Override
public synchronized void putAll(Map values) {
for (Object key : values.keySet()) {
if (! containsKey(key)) {
keySet.add(key);
}
}
super.putAll(values);
}
}
それらが内部でHashtable
として表されているという事実は、それらの順序がいかなる方法でも維持されていないことを意味します。
この機能が絶対に必要な場合は、「独自の」プロパティリーダーを作成することをお勧めします。
この問題を解決するには、「プロパティファイルの順序に基づいてクラスを実行する」。私は通常、次の2つの可能性のいずれかを使用しました。
1-1つのプロパティを、クラス名またはクラス定義のキーとともにコンマ区切りのリストとして使用します
loadClasses = class-definition-A、class-definition-B、class-definition-C
または(「定義」が複数のプロパティで構成されている場合に便利です)
loadClasses = keyA、keyB、keyC
keyA = class-definition-A
keyB = class-definition-B
keyC = class-definition-C
2-キーの後にインデックス(カウンター)を使用します。値が見つからなくなるまで、ループ内のキーを読み取ります。
class1 = class-definition-A
class2 = class-definition-B
class3 = class-definition-C
読み取り順序を記憶し、順序付きキーリストを使用する列挙型を作成するためのサブクラスプロパティ?