Progress28.ru

IT Новости


09ae9cb0
5 просмотров
Рейтинг статьи
1 звезда2 звезды3 звезды4 звезды5 звезд
Загрузка...

Java load properties

Примеры работы с Java Properties

Большинству программ Java в какой-то момент необходимо использовать свойства, как правило, для хранения простых параметров в виде пар ключ-значение вне скомпилированного кода.

Таким образом, язык имеет поддержку класса для свойств — java.util.Properties — служебный класс, предназначенный для обработки файлов конфигурации этого типа.

В этой статье я покажу использование базового класса Properties, в том числе способы загрузки и сохранения в формате XML, как управлять парами ключ-значение в объекте свойств, например извлекать значения, обновлять, получить его размер и как использовать список по умолчанию для объекта.

  • Properties является подклассом Hashtable. Он используется для ведения списков значений, в которых ключ является строкой, а значение также является строкой.
  • Класс Properties используется многими другими классами Java. Например, это тип объекта, возвращаемый System.getProperties() при получении значений.
  • Одна полезная возможность класса состоит в том, что вы можете указать свойство по умолчанию, которое будет возвращаться, если никакое значение не связано с определенным ключом.
  • Несколько потоков могут совместно использовать один объект без необходимости внешней синхронизации.
  • Properties определяет переменную экземпляра.
  • Properties() создает объект Properties, который не имеет значений по умолчанию.
  • Properties (Properties propDefault): второй создает объект, который использует propDefault в качестве значения по умолчанию.
Метод и описание
1String getProperty (String key) Возвращает значение, связанное с ключом. Пустой объект возвращается, если ключ отсутствует в списке или в списке свойств по умолчанию.
2String getProperty (String key, String defaultProperty) возвращает значение, связанное с ключом; defaultProperty возвращается, если ключ не находится ни в списке, ни в списке свойств по умолчанию.
3void list (PrintStream streamOut) Отправляет список свойств в выходной поток, связанный с streamOut.
4void list (PrintWriter streamOut) Отправляет список свойств в выходной поток, связанный с streamOut.
5void load (InputStream streamIn) throws IOException Вводит список свойств из входного потока, связанного с streamIn.
6Перечисление propertyNames() Возвращает перечисление ключей. Сюда входят также ключи, найденные в списке свойств по умолчанию.
7Объект setProperty (String key, String value) Связывает значение с ключом. Возвращает предыдущее значение, связанное с ключом, или возвращает null, если такой ассоциации не существует.
8void store (OutputStream streamOut, String description) После записи строки, указанной в описании, список свойств записывается в выходной поток, связанный с streamOut.

Начнем с примера загрузки пар ключ-значение из файлов свойств; мы загружаем два файла, которые мы имеем в нашем classpath:

Обратите внимание, что в файлах свойств рекомендуется использовать «.properties», в suffix это не обязательно.

Теперь мы можем очень просто загрузить их в экземпляр Properties:

Если содержимое файла соответствует требованиям формата файла свойств, оно может быть правильно проанализировано классом Properties.

Загрузка из файлов XML

Помимо файлов, класс Properties также может загружать файлы XML, которые соответствуют определенным спецификациям DTD.

Вот пример для загрузки пар ключ-значение из файла XML — icons.xml:

Теперь давайте загрузим:

Как получить свойства?

Мы можем использовать getProperty (ключ String) и getProperty (ключ String, String defaultValue), чтобы получить значение по его ключу.

Если пара ключ-значение существует, оба метода будут возвращать соответствующее значение. Но если такой пары ключ-значение не существует, первая вернет null, а вторая вместо нее вернет defaultValue.

Обратите внимание, что хотя класс Properties наследует метод get() от класса Hashtable, я не рекомендую использовать его для получения значения. Поскольку его метод get() будет возвращать значение Object, которое может быть приведено только к String, а метод getProperty() уже обрабатывает значение Object правильно.

Код ниже выдаст исключение:
float appVerFloat = (float) appProps.get(«version»);

Как установить свойства

Мы можем использовать метод setProperty(), чтобы обновить существующую пару ключ-значение или добавить новую.

Класс Properties наследует метод put() и метод putAll() от класса Hashtable, я не рекомендую использовать их по той же причине, что и для метода get(): в свойствах могут использоваться только строковые значения.

Приведенный ниже код не будет работать так, как вы хотите, когда вы используете getProperty() для получения его значения, он вернет null:
appProps.put(«version», 2);

Удалить свойства

Если вы хотите удалить пару ключ-значение, вы можете использовать метод remove().

Хранение Properties

Класс Properties предоставляет метод store() для вывода пар ключ-значение.

Второй параметр используется для комментариев. Если вы не хотите писать какой-либо комментарий, просто используйте для него значение null.

Хранение в XML-файлах

Класс Properties также предоставляет метод storeToXML() для вывода пар ключ-значение в формате XML.

Второй параметр такой же, как и в методе store().

Объект Properties может содержать другой объект Properties в качестве списка свойств по умолчанию. Список свойств по умолчанию будет найден, если ключ свойства не найден в исходном.

Помимо «app.properties», у нас есть еще один файл — «default.properties» — в classpath:

По умолчанию файлы свойств должны быть в кодировке ISO-8859-1 (Latin-1), поэтому обычно не следует использовать свойства с символами не из ISO-8859-1.

Мы можем обойти это ограничение с помощью таких инструментов, как JDK native2ascii или явное кодирование файлов, если это необходимо. Для файлов XML метод loadFromXML() и метод storeToXML() по умолчанию используют кодировку UTF-8.

Однако при чтении XML-файла, закодированного по-другому, мы можем указать это в объявлении DOCTYPE; запись также достаточно гибкая — мы можем указать кодировку в третьем параметре API storeToXML().

Полный исходный код проекта доступен на GitHub

Средняя оценка / 5. Количество голосов:

Спасибо, помогите другим — напишите комментарий, добавьте информации к статье.

Или поделись статьей

Видим, что вы не нашли ответ на свой вопрос.

Чтение конфигурационных файлов в Java: nProperty


Многие разработчики сталкиваются с необходимостью чтения конфигурационных (*.ini, *.prop, *.conf, etc.) файлов в разрабатываемых приложениях. В Java есть стандартный класс Properties, с помощью которого можно очень легко загрузить ini-файл и прочитать его свойства. При большом объеме конфигурационных файлов чтение и запись настроек в объекты превращается в очень нудную и рутинную работу: создать объект Properties, конвертировать каждую настройку в нужный формат и записать его в поле.

Библиотека nProperty (Annotated Property) призвана упростить этот процесс, сократив примерно в два раза требуемый код для написания загрузчиков настроек.

Чтобы показать, каким образом возможно обещанное сокращение кода в два раза, ниже приведены два примера: в первом примере используется стандартный класс Properties, во-втором — nProperty.

Статья и сама библиотека nProperty написана моим другом и товарищем по цеху Yorie для внутрикомандных повседневных нужд, и так как он, к сожалению, не имеет в данный момент инвайта на хабре, я взял на себя смелость, с его согласия, опубликовать сие творение для «хабровских» масс.

Содержание

Просто о главном

В обоих примерах будет использован один и тот же файл конфигурации:

Пример №1. Загрузка конфигурации с помощью стандартного класса Properties.

Пример №2. Загрузка конфигурации с помощью nProperty.

Пожалуй, из этих красивых примеров вытекает факт, что код может быть сокращен даже более, чем в два раза 🙂 В этих примерах не освещены темы присутствия в полях классов переменных, не относящихся к файлам конфигурации, а также еще несколько тонких нюансов. Но обо всем по порядку.

Чтение примитивных и стандартных типов

Во втором вышеприведенном примере стоит обратить внимание на аннотацию @Сfg. Она и является причиной сократившегося кода. Библиотека nProperty основана на аннотациях, которые могут быть применены к классам, полям и методам классов.

Чтобы прочитать из конфигурационного файла настройки, тип которых относится к примитивным, достаточно каждое поле класса обозначить аннотацией @Сfg:

Библиотека nProperty поддерживает достаточно богатый набор стандартных типов:

  • Integer/int
  • Short/short
  • Double/double
  • Long/long
  • Boolean/boolean
  • String
  • Character/char
  • Byte/byte
  • AtomicInteger, AtomicLong, AtomicBoolean
  • BigInteger, BigDecimal

Все эти перечисленные типы могут быть использованы в примере выше.

Десериализация в массивы и коллекции

Помимо стандартных типов также возможна десериализация в массивы с одним условием — тип массива должен принадлежать множеству стандартных типов:

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

Обратите внимание на аннотации у SOME_INT_ARRAY и SOME_SHORT_ARRAY. По умолчанию nProperty использует в качестве разделителя символ «;». Его можно легко переопределить, указав в аннотации к полю свойство splitter. И, как можно заметить, разделителем может выступать полноценное регулярное выражение.

Помимо массивов возможно использование коллекций, а именно — списков. Здесь необходимым является одно условие — коллекция должна быть обязательно проинициализирована до запуска чтения конфигурации. Это связано с тем, что экземпляры объектов коллекций могут быть разными (ArrayList, LinkedList и т.д.):

В остальном для коллекций сохраняются все свойства десериализации массивов.

Десериализация в пользовательские типы

В качестве дополнительной функции библиотека может работать с пользовательскими классами. Пользовательский тип обязательно должен иметь конструктор: MyClass(String), в противном случае будет вызвано исключение. Уровень видимости конструктора не имеет значения, он может быть как public, так и private:

Как видите, библиотеке все равно, что нужный конструктор обозначен модификатором private. В результате в поле value класса T будет записано значение из файла конфигурации.

Модификаторы уровней доступа

Стоит отметить, что библиотеке nProperty абсолютно все равно, какие модификаторы доступа имеет поле, метод или конструктор — библиотека работает через механизм Reflections и управляет этими модификаторами самостоятельно. Конечно же, вмешательство в модификаторы никак не коснется других частей приложения, к которым библиотека отношения не имеет.

Инициализация всех членов класса

В предыдущих примерах видно, что при большом количестве полей в конфигурации придется написать большое кол-во аннотаций @Сfg. Чтобы избежать этой рутинной работы nProperty позволяет добавить аннотацию к самому классу, тем самым обозначив все поля класса как потенциальные поля для записи в них настроек из файла конфигурации:

Здесь стоит обратить внимание на член класса log. Ему назначена аннотация @Сfg с включенным свойством ignore. Это свойство означает, что данное поле не будет использоваться библиотекой при чтении конфигурации, а попросту будет пропущено. Данное свойство следует использовать только в случае, когда аннотация действует на весь класс, как показано в примере выше.

Значения по умолчанию

Одно из замечательных свойств библиотеки в том, что если свойство отсутствует в файле конфигурации, то поле класса никогда не будет изменено. Это позволяет легко выставлять значения по умолчанию прямо в декларации поля класса:

В данном случае после парсинга конфигурации в поле WRONG_PROPERTY будет храниться все то же значение 9000.

Переопределение имен

В случаях, когда имя поля класса не совпадает с именем конфигурации в конфигурационном файле, его можно принудительно переопределить:

Естественно, если есть возможность сохранять равнозначность имен в коде и в файлах конфигурации, то лучше так и делать — это избавит от необходимости аннотировать каждое поле класса.

Работа с не статичными полями классов

Библиотека способна работать как с классами, так и с их экземплярами. Это определяется путем различных вызовов метода ConfigParser.parse():

Как видно, в примере использованы два разных вызова одного и того же метода. После отработки метода ConfigParser.parse(Example11.class, «config/example.ini») в SOME_INT_VALUE будет нуль, причем это совершенно не зависит от файла конфигурации, потому что данное поле не является статичным и не может быть использовано без экземпляра объекта.

Сразу после второго вызова ConfigParser.parse(new Example11(), «config/example.ini») поле SOME_INT_VALUE для созданного объекта примет значение в соответствии с содержанием файла конфигурации.

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

Использование методов

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

Существует три решения в таких ситуациях:

  1. самостоятельно проверить или изменить значение после того, как библиотека проанализирует файл настроек и заполнит все поля класса
  2. создать в качестве типа свой класс-обертку с конструктором (как было показано выше)
  3. исключить поле класса из списка свойств и назначить его методу

Самый удобный и корректный способ — №3. Библиотека nProperty позволяет работать не только с полями, но и с методами:

Здесь в метод checkIntArray(String) в качестве первого параметра будет передано значение SOME_INT_ARRAY из файла конфигурации. Это очень удобный механизм для случаев, когда стандартные решения библиотеки не подходят. В методе-обработчике можно делать все, что угодно.

Однако, стоит отметить, что в случае работы с методами библиотека не использует механизм разделителей, то есть, на данный момент невозможно организовать автоматическое разбиение свойства в массив.

Как и прежде поддерживается преобразование типов, если тип первого параметра метода отличен от String.

Как и с полями класса, если имя метода эквивалентно имени настройки в файле конфигурации, то можно опустить задание имени в аннотации.

Обработка событий

Библиотека nProperty позволяет обрабатывать некоторые события во время чтения конфигурации. Для того, чтобы реализовать обработку событий, необходимо реализовать интерфейс IPropertyListener и все его методы. Вызов событий возможен только в случае работы с полноценными объектами, экземплярами класса, реализующего интерфейс IPropertyListener.

Поддерживаемые события:

  • onStart(String path) — отправляется перед началом загрузки файла конфигурации
  • onPropertyMiss(String name) — вызывается в случае, если некоторая именованная конфигурация не была найдена в файле настроек, но была обозначена в классе аннотацией @Сfg
  • onDone(String path) — вызывается при завершении загрузки файла конфигурации
  • onInvalidPropertyCast(String name, String value) — вызывается в случае, когда удалось прочитать значение настройки из файла конфигурации, но не удалось привести это значение к типу соответствующего поля класса

В приведенном примере будут вызваны все 4 события. Событие onPropertyMiss будет вызвано из-за поля SOME_MISSED_VALUE, которое отсутствует в файле конфигурации. Событие onInvalidPropertyCast будет вызвано из-за неверного типа поля SOME_INT_ARRAY.

Использование потоков и дескрипторов файлов

Библиотека умеет принимать на вход не только имена файлов, также возможна передача объекта java.io.File, или потока данных, производного от абстрактного класса java.io.InputStream:

Как видно, в приведенном примере в случае работы с потоком, библиотека требует дополнительно указать название конфигурации, так как невозможно его получить из низкоуровневого объекта FileInputStream. Название не является важной частью и будет использовано библиотекой для отображения информации (в том числе, при работе с событиями).

Таким образом, данные могут быть получены не только из файловой системы, но и от любого источника данных, работающего по стандартам Java. Умение работать с java.io.InputStream дает возможность библиотеке быть успешно примененной в операционных системах Android:

Замечания

В связи с не очень прозрачной работой SecurityManager’a библиотека имеет ограничение на тип задаваемого поля конфигуратора: поле не должно иметь модификатора final.

Лицензия

Библиотека распространяется по лицензии Apache License v.2.0

Ссылки

Только зарегистрированные пользователи могут участвовать в опросе. Войдите, пожалуйста.

Getting Started with Java Properties

Last modified: May 7, 2019

I just announced the new Learn Spring course, focused on the fundamentals of Spring 5 and Spring Boot 2:

In the 9 years of running Baeldung, I’ve never, ever done a «sale».
But. we’ve also not been through anything like this pandemic either.
And, if making my courses more affordable for a while is going to help a company stay in business, or a developer land a new job, make rent or be able to provide for their family — then it’s well worth doing.
Effective immediately, all Baeldung courses are 33% off their normal prices!
You’ll find all three courses in the menu, above, or here.

1. Overview

Most Java application need to use properties at some point, generally to store simple parameters as key-value pairs, outside of compiled code.

And so the language has first class support for properties – the java.util.Properties – a utility class designed for handling this type of configuration files.

That’s what we’ll focus on in this article.

2. Loading Properties

2.1. From Properties Files

Let’s start with an example for loading key-value pairs from properties files; we’re loading two files we have available on our classpath:

Notice that although the properties files are recommended to use “.properties“, the suffix, it’s not necessary.

We can now load them very simply into a Properties instance:

As long as a file’s content meet properties file format requirements, it can be parsed correctly by Properties class. Here are more details for Property file format.

2.2. Load From XML Files

Besides properties files, Properties class can also load XML files which conform to the specific DTD specifications.

Here is an example for loading key-value pairs from an XML file – icons.xml:

Now, let’s load it:

3. Get Properties

We can use getProperty(String key) and getProperty(String key, String defaultValue) to get value by its key.

If the key-value pair exists, the two methods will both return the corresponding value. But if there is no such key-value pair, the former will return null, and the latter will return defaultValue instead.

Note that although Properties class inherits get() method from Hashtable class, I wouldn’t recommend you use it to get value. Because its get() method will return an Object value which can only be cast to String and the getProperty() method already handles the raw Object value properly for you.

The code below will throw an Exception:

4. Set Properties

We can use setProperty() method to update an existed key-value pair or add a new key-value pair.

Note that although Properties class inherits put() method and putAll() method from Hashtable class, I wouldn’t recommend you use them for the same reason as for get() method: only String values can be used in Properties.

The code below will not work as you wish, when you use getProperty() to get its value, it will return null:

5. Remove Properties

If you want to remove a key-value pair, you can use remove() method.

6. Store

6.1. Store to Properties Files

Properties class provides a store() method to output key-value pairs.

The second parameter is for comment. If you don’t want to write any comment, simply use null for it.

6.2. Store to XML Files

Properties class also provides a storeToXML() method to output key-value pairs in XML format.

The second parameter is as same as it in the store() method.

7. Other Common Operations

Properties class also provides some other methods to operate the properties.

8. Default Property List

A Properties object can contain another Properties object as its default property list. The default property list will be searched if the property key is not found in the original one.

Besides “app.properties“, we have another file – “default.properties” – on our classpath:

9. Properties and Encoding

By default, properties files are expected to be ISO-8859-1 (Latin-1) encoded, so properties with characters outside of the ISO-8859-1 shouldn’t generally be used.

We can work around that limitation with the help of tools such as the JDK native2ascii tool or explicit encodings on files, if necessary.

For XML files, the loadFromXML() method and the storeToXML() method use UTF-8 character encoding by default.

However, when reading an XML file encoded differently, we can specify that in the DOCTYPE declaration; writing is also flexible enough – we can specify the encoding in a third parameter of the storeToXML() API.

10. Conclusion

In this article, we have discussed basic Properties class usage, including how to use Properties load and store key-value pairs in both properties and XML format, how to operate key-value pairs in a Properties object, such as retrieve values, update values, get its size, and how to use a default list for a Properties object.

The complete source code for the example is available in this GitHub project.

29.8. Java – Класс Properties

Properties – это подкласс Hashtable. Он используется для хранения списков значений, в которых ключ является String, а значение также является String.

Класс Properties в Java используется множеством других классов. Например, это тип объекта, возвращаемый System.getProperties(), когда тот получает внешние значения.

Properties определяет следующие переменную экземпляра. Эта переменная содержит список свойств по умолчанию, связанный с объектом Properties.

Следующая программа показывает несколько методов, поддерживаемых этой структурой данных:

Содержание

Конструкторы

Вот список конструкторов, предоставляемые классом Properties.

Конструктор и описание
1Properties()
Этот конструктор создает объёкт Properties, который не имеет значений по умолчанию.
2Properties(Properties propDefault)
Создаёт объект, который использует propDefault для своих значений по умолчанию. В обоих случаях список свойств пустой.

Методы

Помимо методов, определённых Hashtable, Properties определяет следующие методы:

Метод и описание
1String getProperty(String key)
Возвращает значение, связанное с ключом. Возвращается нулевой объект, если ключ не находится ни в списке, ни в списке свойств по умолчанию.
2String getProperty(String key, String defaultProperty)
Возвращает значение, связанное с ключом; Возвращается defaultProperty, если ключ не находится ни в списке, ни в списке свойств по умолчанию.
3void list(PrintStream streamOut)
Отправляет список свойств в выходной поток, связанный с streamOut.
4void list(PrintWriter streamOut)
Отправляет список свойств в выходной поток, связанный с streamOut.
5void load(InputStream streamIn) throws IOException
Вводит список свойств из входного потока, связанного с streamIn.
6Enumeration propertyNames()
Возвращает перечисление ключей, включая ключи, найденные в списке свойств по умолчанию.
7Object setProperty(String key, String value)
Связывает значение с ключом. Возвращает предыдущее значение, связанное с ключом, или возвращает ноль, если такой связи не существует.
8void store(OutputStream streamOut, String description)
После записи строки, указанной в описании, список свойств записывается в выходной поток, связанный с streamOut.

Пример

Следующая программа показывает несколько методов, поддерживаемых этой структурой данных:

Читать еще:  Ошибка приложение сервисы google play остановлено
Ссылка на основную публикацию