web-dev-qa-db-fra.com

Quel est le moyen le plus simple d’analyser un INI déposer en Java?

J'écris une solution de remplacement pour une application existante en Java. L'une des conditions est que les fichiers ini utilisés par l'ancienne application doivent être lus tels quels dans la nouvelle application Java. Le format de ces fichiers ini correspond au style Windows habituel, avec des sections d’en-tête et des paires clé = valeur, en utilisant # comme caractère de commentaire.

J'ai essayé d'utiliser la classe Properties de Java, mais cela ne fonctionnera bien sûr pas s'il y a des conflits de noms entre différents en-têtes.

La question est donc de savoir quel serait le moyen le plus facile de lire dans ce fichier INI et d’accéder aux clés.

93
Mario Ortegón

La bibliothèque que j'ai utilisée est ini4j . Il est léger et analyse facilement les fichiers ini. En outre, il n’utilise aucune dépendance ésotérique pour 10 000 autres fichiers jar, l’un des objectifs de la conception étant d’utiliser uniquement l’API Java standard.

Voici un exemple d'utilisation de la bibliothèque:

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));
112
Mario Ortegón

Comme mentionné , ini4j peut être utilisé pour y parvenir. Laissez-moi vous montrer un autre exemple.

Si nous avons un fichier INI comme celui-ci:

[header]
key = value

Ce qui suit devrait afficher value to STDOUT:

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

Vérifiez les tutoriels pour plus d'exemples.

61
Tshepang

Aussi simple que 80 lignes:

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 ));
   }
}
27
Aerospace

Voici un exemple simple mais puissant, utilisant la classe 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");
}

Configuration commune a un certain nombre de dépendances d'exécution . Au minimum, commons-lang et commons-logging sont requis. Selon votre utilisation, vous aurez peut-être besoin de bibliothèques supplémentaires (voir le lien précédent pour plus de détails).

16
user50217

Ou avec les API Java standard, vous pouvez utiliser Java.util.Properties :

Properties props = new Properties();
try (FileInputStream in = new FileInputStream(path)) {
    props.load(in);
}
11
Peter

En 18 lignes, extension du Java.util.Properties à analyser en plusieurs sections:

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("]"))
                return result.put(header.substring(1, header.length() - 1), 
                        section = new Properties());
            else
                return section.put(key, value);
        }

    }.load(reader);
    return result;
}
7
hoat4

Une autre option est Apache Commons Config a aussi une classe pour charger depuis INI fichiers . Il a quelques dépendances d'exécution , mais pour les fichiers INI, il ne devrait nécessiter que des collectes communes, des langages et une journalisation. 

J'ai utilisé Commons Config sur des projets avec leurs propriétés et leurs configurations XML. Il est très facile à utiliser et supporte des fonctionnalités assez puissantes. 

2
John Meagher

Vous pouvez essayer JINIFile. Est une traduction du TIniFile de Delphi, mais pour Java

https://github.com/SubZane/JIniFile

2
Andreas Norman

Personnellement, je préfère Confucious .

C'est agréable, car il ne nécessite aucune dépendance externe, il est minuscule - seulement 16K, et charge automatiquement votre fichier ini à l'initialisation. Par exemple.

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