web-dev-qa-db-fra.com

Comment puis-je écrire des propriétés Java dans un ordre défini?

J'utilise la méthode store (Writer, String) de Java.util.Properties pour stocker les propriétés. Dans le fichier texte résultant, les propriétés sont stockées dans un ordre aléatoire. 

Voici ce que je fais:

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

Comment puis-je m'assurer que les propriétés sont écrites dans l'ordre alphabétique ou dans l'ordre d'ajout des propriétés?

J'espère une solution plus simple que "créer manuellement le fichier de propriétés".

26
Steve McLeod

Selon la suggestion de "The New Idiot", cette option est stockée dans l'ordre alphabétique des clés.

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

Voir https://github.com/etiennestuder/Java-ordered-properties pour une implémentation complète permettant de lire/écrire des fichiers de propriétés dans un ordre bien défini.

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

Utiliser TreeSet est dangereux! Parce que dans le CASE_INSENSITIVE_ORDER, les chaînes "mykey", "MyKey" et "MYKEY" donneront le même index! (donc 2 clés seront omises).

J'utilise plutôt List, pour être sûr de garder toutes les clés.

 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

La solution de Steve McLeod n'a pas fonctionné lorsque vous avez essayé de trier la casse.

C'est ce que je suis venu avec

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

La réponse de Steve McLeod fonctionnait pour moi auparavant, mais pas depuis Java 11.

Le problème semblait être la commande EntrySet, alors, voici:

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

Je préviens que ce n'est pas rapide, loin de là. Cela force l'itération sur un LinkedHashSet qui n'est pas idéal, mais je suis ouvert aux suggestions.

0
ComputerEngineer88