2010-09-01 14 views
13

Necesito leer un archivo de propiedades y generar una clase de propiedades en Java. Y lo hago mediante el uso de:Cómo leer un archivo de propiedades en java en el orden original

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

Sin embargo, las propiedades devueltas por props.propertyName no está en el orden del archivo de propiedades originales. Entiendo que las propiedades son simplemente Hashtables anticuadas y no generizadas. Estoy buscando un trabajo alrededor. ¿Alguna idea? ¡Gracias!

+0

alguna razón en particular que el orden importa? – Powerlord

+0

Necesito ejecutar clases basadas en el orden en el archivo de propiedades. – wen

+0

En realidad se genera, como 'Hashtable ' (hay una pregunta sobre por qué está en algún lugar). –

Respuesta

6

Es posible que desee implementar su propia clase de Propiedades con funcionalidades similares. No será posible obtener el pedido ya que, como ya ha señalado, usa Hashtable.

+7

Enlace roto para sugerencias. –

+0

Enlace roto. o es un anuncio –

2

El hecho de que estén representados como Hashtable debajo del capó significa que su orden no se mantiene de ninguna manera.

Le sugiero que "saque su propio" lector de propiedades si está absolutamente desesperado por esta funcionalidad.

+2

No hay nada "oculto" sobre el uso de 'Hashtable' -' Properties extends Hashtable '. –

0

Subclase ¿Propiedades para memorizar el orden de lectura y crear una enumeración que utiliza la lista de teclas ordenadas?

13

Puede ampliar Propiedades y delegar todos los métodos de mapa en LinkedHashMap para conservar el orden. Aquí hay un ejemplo (puede que tenga que reemplazar algunos de los métodos más):

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

Agradable y simple. Puede simplificarse almacenando valores tanto en 'super' como en' linkMap' y solo puede anular las operaciones de modificación e iteración. p.ej. 'put' {linkedMap.put (clave, valor); return super.put (clave, valor); } – karmakaze

+0

Sugeriría '@ Override' también' size() 'y' toString() ' –

+0

@ToKra obviamente, sí. gracias –

16

Ejemplo de www.java2s.com debería resolver su problema.

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; 

} 

Y su código cambiará a:

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

Es posible que desee considerar que la pregunta podría interpretarse en el sentido de que queremos leer un archivo original que no se creó mediante programación o no creado con su clase OrderedProperties. En tales casos, la solución ofrecida no es una solución. – H2ONaCl

+1

@broiyan Esta solución debería funcionar independientemente de cómo se crea el archivo de propiedades. – YoK

+0

Esto funciona como un encanto. Lo usé de la siguiente manera: Propiedades properties = new OrderedProperties(); Mapa propertyFileMap = new LinkedHashMap <>(); Enumeración propertyKeyNames = (Enumeración ) properties.propertyNames(); while (propertyKeyNames.hasMoreElements()) { Cadena propertyKey = propertyKeyNames.nextElement(); Cadena propertyValue = properties.getProperty (propertyKey); propertyFileMap.put (propertyKey, propertyValue); } –

0

Para resolver el problema: "para ejecutar las clases en función del orden en el archivo de propiedades." Solía ​​normalmente uno de los 2 posibilidades:

1 - utilizar una propiedad como una lista separada por comas con los nombres de clase o con las teclas a la definición de clase

loadClasses = clase definición-A, clase definición-B, clase definición-C

o (útil si la "definición" se compone de más de una propiedad)

loadClasses = KEYA, keyb, keyc
KEYA = clase definición-A
keyb = clase definición-B
keyc = clase definición-C


2 - utilizar una clave seguido por un índice (contador). Lea las teclas en un bucle hasta que no se encuentre ningún valor.

class1 = clase definición-A
clase2 = clase definición-B
Class3 = clase definición-C

7

similares a uno de los anteriores, pero w/out la sobrecarga de mantener nuestra propia lista de valores. Todo lo que tenemos que hacer es mantener una lista ordenada por separado de las claves y proporcionar un nuevo método "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é tal, en este punto, usar un 'LinkedHashSet' y evitar todos esos' containsKey'? – Campa

1

La correcta aplicación del conjunto de claves:

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()' llamada son bastante irrelevantes aquí, ¿verdad? PD para lectores no rusos: ¡ese temible cirílico _правильной реализацией_ significa "implementación correcta"! – Campa

+0

¡Hola! contains() ser agradable de agregar. Scary cirylic replace by natural english :) – GKislin

+0

¿Por qué los métodos 'load' no son anulados? – Stephan

3

plena aplicación basada en 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()); 
    } 
} 

Resultado:

--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

solo esto funcionó para mí. Leyó archivos de propiedades en secuencias reales. – linuxeasy

Cuestiones relacionadas