Как я могу написать свойства Java в определенном порядке?
Я использую метод хранения java.util.Properties(Writer, String) для хранения свойств. В результирующем текстовом файле свойства хранятся в случайном порядке.
Это то, что я делаю:
Properties properties = createProperties();
properties.store(new FileWriter(file), null);
Как я могу гарантировать, что свойства записываются в алфавитном порядке или в порядке добавления свойств?
Я надеюсь на решение проще, чем "вручную создать файл свойств".
Ответы
Ответ 1
В соответствии с предложением "Новый Идиот" это хранится в алфавитном порядке.
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);
Ответ 2
См. https://github.com/etiennestuder/java-ordered-properties для полной реализации, которая позволяет читать/записывать файлы свойств в определенном порядке.
OrderedProperties properties = new OrderedProperties();
properties.load(new FileInputStream(new File("~/some.properties")));
Ответ 3
Решение от Steve McLeod не срабатывало при попытке сортировки без учета регистра.
Вот что я придумал
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);
}
Ответ 4
Использовать TreeSet
опасно! Потому что в CASE_INSENSITIVE_ORDER
строки "mykey", "MyKey" и "MYKEY" приведут к одному и тому же индексу! (поэтому 2 ключа будут опущены).
Вместо этого я использую List
, чтобы сохранить все ключи.
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 );
Ответ 5
Ответ Стива Маклеода раньше работал на меня, но начиная с Java 11, это не так.
Казалось, проблема заключается в заказе EntrySet, так что вот, пожалуйста:
@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)));
}
};
}
Я предупрежу, что это не быстро любым способом. Он заставляет перебирать LinkedHashSet, что не идеально, но я открыт для предложений.