Pregunta

Estoy escribiendo un reemplazo directo para una aplicación heredada en Java. Uno de los requisitos es que los archivos ini que usaba la aplicación anterior debían leerse tal cual en la nueva aplicación Java. El formato de estos archivos ini es el estilo común de Windows, con secciones de encabezado y pares clave = valor, utilizando # como carácter para comentar.

Intenté usar la clase Propiedades de Java, pero por supuesto eso no funcionará si hay conflictos de nombres entre diferentes encabezados.

Entonces, la pregunta es, ¿cuál sería la forma más fácil de leer este archivo INI y acceder a las claves?

¿Fue útil?

Solución

La biblioteca que he usado es ini4j . Es liviano y analiza los archivos ini con facilidad. Además, no utiliza dependencias esotéricas de otros 10.000 archivos jar, ya que uno de los objetivos de diseño era usar solo la API Java estándar

Este es un ejemplo de cómo se usa la biblioteca:

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

Otros consejos

Como mencionado , ini4j se puede utilizar para lograr esto. Déjame mostrarte otro ejemplo.

Si tenemos un archivo INI como este:

[header]
key = value

Lo siguiente debe mostrar el valor en STDOUT:

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

Consulte los tutoriales para obtener más ejemplos.

Tan simple como 80 líneas:

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

Aquí hay un ejemplo simple pero poderoso, usando la clase 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");
}

La configuración de Commons tiene varias dependencias de tiempo de ejecución . Como mínimo, commons-lang y commons-logging son obligatorios. Dependiendo de lo que esté haciendo con él, es posible que necesite bibliotecas adicionales (consulte el enlace anterior para más detalles).

O con la API Java estándar puede usar java .util.Properties :

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

En 18 líneas, extendiendo java.util.Properties para analizar en varias secciones:

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

Otra opción es Apache Commons Config también tiene una clase para cargar desde archivos INI . Tiene algunas dependencias de tiempo de ejecución , pero para los archivos INI solo debe requerir colecciones de Commons, lang y registro.

He usado Commons Config en proyectos con sus propiedades y configuraciones XML. Es muy fácil de usar y admite algunas funciones bastante potentes.

Puedes probar JINIFile. Es una traducción del TIniFile de Delphi, pero para Java

https://github.com/SubZane/JIniFile

Personalmente prefiero Confucious .

Es agradable, ya que no requiere dependencias externas, es pequeño, solo 16K y carga automáticamente su archivo ini en la inicialización. Por ejemplo,

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

Es tan simple como esto .....

//import java.io.FileInputStream;
//import java.io.FileInputStream;

Properties prop = new Properties();
//c:\\myapp\\config.ini is the location of the ini file
//ini file should look like host=localhost
prop.load(new FileInputStream("c:\\myapp\\config.ini"));
String host = prop.getProperty("host");
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top