Каков самый простой способ разбора INI файла на Java?

Я пишу замену для старого приложения на Java. Одним из требований является то, что файлы ini, которые использовалось старым приложением, должны быть прочитаны как есть в новом Java-приложении. Формат этих ini файлов - это общий стиль Windows, с заголовками и парами ключ = значение, используя # в качестве символа для комментариев.

Я попытался использовать класс Properties из Java, но, конечно, это не сработает, если между разными заголовками есть столкновение имен.

Итак, вопрос в том, что было бы самым простым способом прочитать в этом INI файле и получить доступ к ключам?

Ответ 1

Библиотека, которую я использовал, ini4j. Он легкий и легко анализирует файлы ini. Также он не использует эзотерических зависимостей для 10 000 других файлов jar, поскольку одной из целей дизайна было использование только стандартного API Java

Это пример использования библиотеки:

Ini ini = new Ini(new File(filename));
java.util.prefs.Preferences prefs = new IniPreferences(ini);
System.out.println("grumpy/homePage: " + prefs.node("grumpy").get("homePage", null));

Ответ 2

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

Если у нас есть файл INI, например:

[header]
key = value

Следующее должно отображать value в STDOUT:

Ini ini = new Ini(new File("/path/to/file"));
System.out.println(ini.get("header", "key"));

Подробнее о учебниках.

Ответ 3

Проще всего 80 строк:

package windows.prefs;

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class IniFile {

   private Pattern  _section  = Pattern.compile( "\\s*\\[([^]]*)\\]\\s*" );
   private Pattern  _keyValue = Pattern.compile( "\\s*([^=]*)=(.*)" );
   private Map< String,
      Map< String,
         String >>  _entries  = new HashMap<>();

   public IniFile( String path ) throws IOException {
      load( path );
   }

   public void load( String path ) throws IOException {
      try( BufferedReader br = new BufferedReader( new FileReader( path ))) {
         String line;
         String section = null;
         while(( line = br.readLine()) != null ) {
            Matcher m = _section.matcher( line );
            if( m.matches()) {
               section = m.group( 1 ).trim();
            }
            else if( section != null ) {
               m = _keyValue.matcher( line );
               if( m.matches()) {
                  String key   = m.group( 1 ).trim();
                  String value = m.group( 2 ).trim();
                  Map< String, String > kv = _entries.get( section );
                  if( kv == null ) {
                     _entries.put( section, kv = new HashMap<>());   
                  }
                  kv.put( key, value );
               }
            }
         }
      }
   }

   public String getString( String section, String key, String defaultvalue ) {
      Map< String, String > kv = _entries.get( section );
      if( kv == null ) {
         return defaultvalue;
      }
      return kv.get( key );
   }

   public int getInt( String section, String key, int defaultvalue ) {
      Map< String, String > kv = _entries.get( section );
      if( kv == null ) {
         return defaultvalue;
      }
      return Integer.parseInt( kv.get( key ));
   }

   public float getFloat( String section, String key, float defaultvalue ) {
      Map< String, String > kv = _entries.get( section );
      if( kv == null ) {
         return defaultvalue;
      }
      return Float.parseFloat( kv.get( key ));
   }

   public double getDouble( String section, String key, double defaultvalue ) {
      Map< String, String > kv = _entries.get( section );
      if( kv == null ) {
         return defaultvalue;
      }
      return Double.parseDouble( kv.get( key ));
   }
}

Ответ 4

Вот простой, но мощный пример использования класса apache HierarchicalINIConfiguration:

HierarchicalINIConfiguration iniConfObj = new HierarchicalINIConfiguration(iniFile); 

// Get Section names in ini file     
Set setOfSections = iniConfObj.getSections();
Iterator sectionNames = setOfSections.iterator();

while(sectionNames.hasNext()){

 String sectionName = sectionNames.next().toString();

 SubnodeConfiguration sObj = iniObj.getSection(sectionName);
 Iterator it1 =   sObj.getKeys();

    while (it1.hasNext()) {
    // Get element
    Object key = it1.next();
    System.out.print("Key " + key.toString() +  " Value " +  
                     sObj.getString(key.toString()) + "\n");
}

Конфигурация Commons имеет ряд зависимостей времени выполнения. Как минимум, commons-lang и commons-logging являются обязательный. В зависимости от того, что вы делаете с ним, вам могут потребоваться дополнительные библиотеки (подробности см. В предыдущей ссылке).

Ответ 5

Или со стандартным API Java вы можете использовать java.util.Properties:

new Properties() props = rowProperties.load(new FileInputStream(path));

Ответ 6

Другой вариант Apache Commons Config также имеет класс для загрузки из Файлы INI. Он имеет некоторые зависимостей времени исполнения, но для файлов INI ему нужны только коллекции Commons, lang и logging.

Я использовал Commons Config для проектов с их свойствами и конфигурациями XML. Он очень прост в использовании и поддерживает некоторые довольно мощные функции.

Ответ 7

Вы можете попробовать JINIFile. Является переводом TIniFile из Delphi, но для java

https://github.com/SubZane/JIniFile

Ответ 8

В 19 строках, расширяя java.util.Properties, чтобы проанализировать несколько разделов:

public static Map<String, Properties> parseINI(Reader reader) throws IOException {
    Map<String, Properties> result = new HashMap();
    new Properties() {

        private Properties section;

        @Override
        public Object put(Object key, Object value) {
            String header = (((String) key) + " " + value).trim();
            if (header.startsWith("[") && header.endsWith("]"))
                result.put(header.substring(1, header.length() - 1), 
                        section = new Properties());
            else
                section.put(key, value);
            return null;
        }

    }.load(reader);
    return result;
}

Ответ 9

Я лично предпочитаю Confucious.

Хорошо, так как он не требует каких-либо внешних зависимостей, он крошечный - всего 16 КБ и автоматически загружает ваш ini файл при инициализации. Например.

Configurable config = Configuration.getInstance();  
String host = config.getStringValue("host");   
int port = config.getIntValue("port"); 
new Connection(host, port);