Qual è il modo più semplice per analizzare un file INI in Java?

Sto scrivendo una sostituzione drop-in per un’applicazione legacy in Java. Uno dei requisiti è che i file ini utilizzati dall’applicazione precedente devono essere letti come nella nuova applicazione Java. Il formato di questo file ini è lo stile Windows comune, con sezioni di intestazione e coppie chiave = valore, utilizzando # come carattere per i commenti.

Ho provato a utilizzare la class Properties da Java, ma ovviamente non funzionerà se ci sono conflitti di nome tra diverse intestazioni.

Quindi la domanda è, quale sarebbe il modo più semplice per leggere in questo file INI e accedere ai tasti?

La libreria che ho usato è ini4j . È leggero e analizza facilmente i file ini. Inoltre, non utilizza dipendenze esoteriche per 10.000 altri file jar, poiché uno degli obiettivi di progettazione era l’utilizzo solo dell’API Java standard

Questo è un esempio di come viene utilizzata la libreria:

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

Come accennato , ini4j può essere utilizzato per raggiungere questo objective. Lasciatemi mostrare un altro esempio.

Se abbiamo un file INI come questo:

 [header] key = value 

Quanto segue dovrebbe mostrare il value di STDOUT:

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

Controlla le esercitazioni per altri esempi.

Semplice come 80 linee:

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

Ecco un esempio semplice ma potente, utilizzando la class di 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 Configuration ha un numero di dipendenze di runtime . Come minimo sono richiesti comuni-lang e commons-logging . A seconda di cosa stai facendo, potresti richiedere librerie aggiuntive (vedi il link precedente per i dettagli).

Oppure con l’API Java standard puoi usare java.util.Properties :

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

In 19 righe, estendere java.util.Properties per l’analisi in più sezioni:

 public static Map parseINI(Reader reader) throws IOException { Map 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; } 

Un’altra opzione è Apache Commons Config ha anche una class per il caricamento da file INI . Ha alcune dipendenze di runtime , ma per i file INI dovrebbe solo richiedere raccolte di Commons, lang e logging.

Ho usato Commons Config su progetti con le loro proprietà e configurazioni XML. È molto facile da usare e supporta alcune funzioni piuttosto potenti.

Potresti provare JINIFile. È una traduzione di TIniFile da Delphi, ma per java

https://github.com/SubZane/JIniFile

Personalmente preferisco Confucious .

È bello, in quanto non richiede alcuna dipendenza esterna, è minuscolo – solo 16K e carica automaticamente il tuo file ini all’inizializzazione. Per esempio

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