2010-09-01 2 views
13

Мне нужно прочитать файл свойств и сгенерировать класс на Java. Я делаю это с помощью:Как читать файл свойств в java в исходном порядке

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

Однако свойства, возвращаемые props.propertyName не в порядке исходного файла свойств. Я понимаю, что Свойства - это просто старомодные, невоспитанные Hashtables. Я ищу работу. Есть идеи? Спасибо!

+0

Любая конкретная причина того, что порядок имеет значение? – Powerlord

+0

Мне нужно выполнить классы на основе порядка в файле свойств. – wen

+0

На самом деле он генерируется как «Hashtable » (возникает вопрос, почему это где-то). –

ответ

6

Возможно, вы захотите реализовать свой собственный класс свойств с аналогичными функциями. Вы не сможете получить заказ, поскольку, как вы уже указали, он использует Hashtable.

+7

Неработающая ссылка для предложения. –

+0

Неработающая ссылка. или это реклама –

2

Тот факт, что они представлены как Hashtable под капотом, означает, что их заказ не хранится ни в коем случае.

Я предлагаю вам «сканировать свой собственный» читатель свойств, если вы абсолютно отчаянно нуждаетесь в этой функции.

+2

Нет ничего «под капотом» об использовании 'Hashtable' -' Свойства extends Hashtable '. –

0

Свойства подкласса для запоминания порядка чтения и создания перечисления, в котором используется список упорядоченных ключей?

13

Вы можете расширить свойства и делегировать все методы карты на 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); 
    } 

} 
+0

Ницца и просто. Можно упростить, сохраняя значения как в «супер», так и в «linkMap», а затем может переопределять операции модификации и итерации. например 'put' {linkedMap.put (ключ, значение); return super.put (ключ, значение); } – karmakaze

+0

Я бы предложил '@ Override' также' size() 'и' toString() ' –

+0

@ToKra, очевидно, да. спасибо –

16

Пример из 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();) { 
} 
+1

Возможно, вам стоит подумать, что вопрос может быть истолкован как означающий, что мы хотим прочитать исходный файл, который не был создан программно или не создан с помощью ваш класс OrderedProperties. В таких случаях предлагаемое решение не является решением. – H2ONaCl

+1

@broiyan Это решение должно работать независимо от того, как создается файл свойств. – YoK

+0

Это работает как шарм. Я использовал его следующим образом: Свойства properties = new OrderedProperties(); Карта свойствоFileMap = new LinkedHashMap <>(); Перечисление propertyKeyNames = (Перечисление ) properties.propertyNames(); while (propertyKeyNames.hasMoreElements()) { Свойство StringKey = propertyKeyNames.nextElement(); String propertyValue = properties.getProperty (propertyKey); propertyFileMap.put (свойствоKey, propertyValue); } –

0

Чтобы решить эту проблему: «выполнять классы на основе порядка в файле свойств.» Я обычно используется один из 2-х возможностей:

1 - использовать одно свойство как разделенный запятыми список с классом названий или с ключами к определению класса

loadClasses = класса четкости-A, класс четкости-в, класс-определение-С

или (полезно, если "определение" состоит из более чем одного свойства)

loadClasses = Keya, KEYB, keyC
Keya = Класс четкость-А
KEYB = Класс четкость-Б
keyC = Класс четкость-С


2 - использовать ключ с последующим индексом (счетчик). Прочитайте ключи в цикле, пока не будет найдено значение.

class1 = Класс четкости-А
class2 = Класс четкости-Б
class3 = Класс четкости-С

7

Аналогично из приведенных выше пунктов, но ж/из накладных расходов сохранения нашего собственного списка ценностей. Все, что нам нужно сделать, это сохранить отдельный упорядоченный список ключей и предоставить новый метод «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

Как насчет, на данный момент, с помощью 'LinkedHashSet' и избегать всех этих' containsKey'? – Campa

1

Правильная реализация 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()' звонок здесь совершенно неактуальен, правильно? PS для нерусских читателей: эта страшная кириллица _правильной реализацией_ означает «правильная реализация»! – Campa

+0

Привет! contains() быть приятно добавить. Страшная кириллица заменяется естественным английским :) – GKislin

+0

Почему методы 'load' не переоцениваются? – Stephan

3

полная реализация на основе 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} 
+0

только это сработало для меня. Он действительно читал файлы свойств в реальных последовательностях. – linuxeasy

Смежные вопросы