2010-09-01 8 views
13

Je dois lire un fichier de propriétés et générer une classe de propriétés en Java. Je le fais en utilisant:Comment lire un fichier de propriétés dans java dans l'ordre original

Properties props = new Properties(); 
props.load(new FileInputStream(args[0])); 
for (Enumeration e = props.propertyNames(); e.hasMoreElements();) { 
} 

Cependant, les propriétés retournées par props.propertyName ne sont pas dans l'ordre du fichier de propriétés d'origine. Je comprends que Propriétés sont juste démodé, Hashtables non-génératif. Je cherche un travail autour. Une idée? Je vous remercie!

+0

Une raison particulière que les matters ordre? – Powerlord

+0

J'ai besoin d'exécuter des classes en fonction de l'ordre dans le fichier de propriétés. – wen

+0

Il est en fait généré, comme 'Hashtable ' (il y a une question de savoir pourquoi c'est quelque part). –

Répondre

6

Vous pouvez implémenter votre propre classe de propriétés avec des fonctionnalités similaires. Il ne vous sera pas possible d'obtenir la commande car, comme vous l'avez déjà indiqué, elle utilise Hashtable.

+7

Lien brisé pour suggestion. –

+0

Lien brisé. ou c'est une publicité –

2

Le fait qu'ils soient représentés sous la forme d'un Hashtable signifie que leur commande n'est pas conservée de quelque manière que ce soit.

Je vous suggère de "rouler votre propre" lecteur de propriétés si vous êtes absolument désespéré pour cette fonctionnalité. Sous-classe

+2

Il n'y a rien "sous le capot" sur l'utilisation de 'Hashtable' -' Propriétés étend Hashtable '. –

0

Sous-classe Propriétés permettant de mémoriser l'ordre de lecture et de créer une énumération utilisant la liste des clés commandées?

13

Vous pouvez étendre les propriétés et déléguer toutes les méthodes de carte à LinkedHashMap pour conserver la commande. Voici un exemple (vous devrez peut-être remplacer quelques autres méthodes):

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); 
    } 

} 
+0

Agréable et simple. Peut être simplifié en stockant des valeurs dans 'super' et' linkMap' et ne peut que remplacer les opérations de type modify et itération. par exemple. 'put' {linkedMap.put (clé, valeur); return super.put (clé, valeur); } – karmakaze

+0

Je suggérerais '@ Override' aussi' size() 'et' toString() ' –

+0

@ToKra évidemment, oui. grâce –

16

Exemple de www.java2s.com devrait résoudre votre problème.

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; 

} 

Et votre code va changer à:

Properties props = new OrderedProperties(); 
props.load(new FileInputStream(args[0])); 
for (Enumeration e = props.propertyNames(); e.hasMoreElements();) { 
} 
+1

vous pourriez vouloir considérer que la question pourrait être interprétée comme signifiant que nous voulons lire un fichier original qui n'a pas été créé ou non créé par programme avec votre classe OrderedProperties. Dans de tels cas, la solution proposée n'est pas une solution. – H2ONaCl

+1

@broiyan Cette solution devrait fonctionner indépendamment du mode de création du fichier de propriétés. – YoK

+0

Cela fonctionne comme un charme. Je l'ai utilisé comme suit: Properties properties = new OrderedProperties(); Mappe propertyFileMap = new LinkedHashMap <>(); Énumération propertyKeyNames = (Énumération ) properties.propertyNames(); while (propriétéKeyNames.hasMoreElements()) { String propertyKey = propertyKeyNames.nextElement(); String propertyValue = properties.getProperty (propriétéKey); propertyFileMap.put (propriétéKey, propertyValue); } –

0

Pour résoudre le problème: « pour exécuter des cours en fonction de l'ordre dans le fichier de propriétés. » Je normalement utilisé l'une des 2 possibilités:

1 - utiliser une propriété comme une liste séparée par des virgules avec les noms de classe ou avec les clés de la définition de la classe

loadClasses = class-définition-A, définition de classe B, classe C-définition

ou (utile si la "définition" se compose de plus d'une propriété)

loadClasses = keya, keyb, KEYc
keya = class-A-définition
keyb = class-définition-B
KEYc = class-définition-C


2 - utiliser une clé suivi d'un index (compteur). Lire les clés dans une boucle jusqu'à ce qu'aucune valeur ne soit trouvée.

Class1 = class-définition-A
class2 = class-définition-B
class3 = class-définition-C

7

semblable à l'un de ce qui précède, mais w/la surcharge de maintenir notre propre liste de valeurs. Tout ce que nous avons à faire est de maintenir une liste ordonnée séparée des clés, et de fournir une nouvelle méthode "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); 
    } 
} 
+0

Qu'en est-il, à ce stade, en utilisant un 'LinkedHashSet' et éviter tous ces' containsKey'? – Campa

1

mise en œuvre correcte de 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); 
    } 
} 
+0

Ihmo '.contains()' appel sont tout à fait hors de propos ici, non? PS pour les lecteurs non-russes: ce cyrillique effrayant _правильной реализацией_ signifie "bonne mise en œuvre"! – Campa

+0

Bonjour! contient() être agréable à ajouter. Effrayant cyrillic remplacer par l'anglais naturel :) – GKislin

+0

Pourquoi les méthodes 'load' ne sont pas remplacées? – Stephan

3

mise en œuvre complète basée sur 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()); 
    } 
} 

Résultat:

--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} 
+0

seulement cela a fonctionné pour moi. Il a lu les fichiers de propriétés dans des séquences réelles. – linuxeasy