it-swarm.com.de

Wie schreibe ich Java-Eigenschaften in einer definierten Reihenfolge?

Ich verwende die Methode store (Writer, String) von Java.util.Properties, um die Eigenschaften zu speichern. In der resultierenden Textdatei werden die Eigenschaften in zufälliger Reihenfolge gespeichert. 

Das mache ich:

Properties properties = createProperties();
properties.store(new FileWriter(file), null);

Wie kann ich sicherstellen, dass die Eigenschaften in alphabetischer Reihenfolge geschrieben werden oder in der Reihenfolge, in der die Eigenschaften hinzugefügt wurden?

Ich hoffe auf eine Lösung, die einfacher ist als das Erstellen der Eigenschaftendatei.

26
Steve McLeod

Gemäß dem Vorschlag von "The New Idiot" wird dies in alphabetischer Reihenfolge gespeichert.

Properties tmp = new Properties() {
    @Override
    public synchronized Enumeration<Object> keys() {
        return Collections.enumeration(new TreeSet<Object>(super.keySet()));
    }
};
tmp.putAll(properties);
tmp.store(new FileWriter(file), null);
55
Steve McLeod

Unter https://github.com/etiennestuder/Java-ordered-properties finden Sie eine vollständige Implementierung, die das Lesen/Schreiben von Eigenschaftendateien in einer definierten Reihenfolge ermöglicht.

OrderedProperties properties = new OrderedProperties();
properties.load(new FileInputStream(new File("~/some.properties")));
9
Etienne Studer

Die Verwendung einer TreeSet ist gefährlich! Im CASE_INSENSITIVE_ORDER führen die Zeichenfolgen "mykey", "MyKey" und "MYKEY" zum gleichen Index! (so werden 2 Schlüssel weggelassen).

Ich benutze stattdessen List, um sicherzugehen, dass alle Schlüssel erhalten bleiben.

 List<Object> list = new ArrayList<>( super.keySet());
 Comparator<Object> comparator = Comparator.comparing( Object::toString, String.CASE_INSENSITIVE_ORDER );
 Collections.sort( list, comparator );
 return Collections.enumeration( list );
1
Dorian Gray

Die Lösung von Steve McLeod funktionierte nicht, wenn versucht wurde, die Groß- und Kleinschreibung zu unterscheiden.

Das ist was ich gefunden habe

Properties newProperties = new Properties() {

    private static final long serialVersionUID = 4112578634029874840L;

    @Override
    public synchronized Enumeration<Object> keys() {
        Comparator<Object> byCaseInsensitiveString = Comparator.comparing(Object::toString,
                        String.CASE_INSENSITIVE_ORDER);

        Supplier<TreeSet<Object>> supplier = () -> new TreeSet<>(byCaseInsensitiveString);

        TreeSet<Object> sortedSet = super.keySet().stream()
                        .collect(Collectors.toCollection(supplier));

        return Collections.enumeration(sortedSet);
    }
 };

    // propertyMap is a simple LinkedHashMap<String,String>
    newProperties.putAll(propertyMap);
    File file = new File(filepath);
    try (FileOutputStream fileOutputStream = new FileOutputStream(file, false)) {
        newProperties.store(fileOutputStream, null);
    }
1
kevcodez

Steve McLeods Antwort funktionierte früher für mich, aber seit Java 11 nicht.

Das Problem schien die Bestellung von EntrySet zu sein, also los geht's:

@SuppressWarnings("serial")
private static Properties newOrderedProperties() 
{
    return new Properties() {
        @Override public synchronized Set<Map.Entry<Object, Object>> entrySet() {
            return Collections.synchronizedSet(
                    super.entrySet()
                    .stream()
                    .sorted(Comparator.comparing(e -> e.getKey().toString()))
                    .collect(Collectors.toCollection(LinkedHashSet::new)));
        }
    };
}

Ich werde darauf hinweisen, dass dies keinesfalls schnell ist. Es zwingt die Iteration über ein LinkedHashSet, das nicht ideal ist, aber ich bin offen für Vorschläge.

0