在Java中解析INI文件的最简单方法是什么?

时间:2022-06-12 15:22:47

I am writing a drop-in replacement for a legacy application in Java. One of the requirements is that the ini files that the older application used have to be read as-is into the new Java Application. The format of this ini files is the common windows style, with header sections and key=value pairs, using # as the character for commenting.

我正在为Java中的遗留应用程序编写替代品。其中一个要求是旧应用程序使用的ini文件必须按原样读入新的Java应用程序。此ini文件的格式是常见的Windows样式,带有标题部分和键=值对,使用#作为注释字符。

I tried using the Properties class from Java, but of course that won't work if there is name *es between different headers.

我尝试使用Java中的Properties类,但是如果不同标头之间存在名称冲突,那么这当然不起作用。

So the question is, what would be the easiest way to read in this INI file and access the keys?

所以问题是,在这个INI文件中读取和访问密钥的最简单方法是什么?

9 个解决方案

#1


107  

The library I've used is ini4j. It is lightweight and parses the ini files with ease. Also it uses no esoteric dependencies to 10,000 other jar files, as one of the design goals was to use only the standard Java API

我用的库是ini4j。它很轻巧,可以轻松解析ini文件。此外,它不会对10,000个其他jar文件使用深奥的依赖关系,因为其中一个设计目标是仅使用标准Java API

This is an example on how the library is used:

这是关于如何使用库的示例:

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


60  

As mentioned, ini4j can be used to achieve this. Let me show one other example.

如上所述,ini4j可用于实现此目的。让我再举一个例子。

If we have an INI file like this:

如果我们有这样的INI文件:

[header]
key = value

The following should display value to STDOUT:

以下应显示STDOUT的值:

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

Check the tutorials for more examples.

查看教程以获取更多示例。

#3


25  

As simple as 80 lines:

简单到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


15  

Here's a simple, yet powerful example, using the apache class HierarchicalINIConfiguration:

这是一个简单而强大的示例,使用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 has a number of runtime dependencies. At a minimum, commons-lang and commons-logging are required. Depending on what you're doing with it, you may require additional libraries (see previous link for details).

Commons Configuration具有许多运行时依赖性。至少需要公共区域和公共区域记录。根据您正在使用的内容,您可能需要其他库(有关详细信息,请参阅上一个链接)。

#5


12  

Or with standard Java API you can use java.util.Properties:

或者使用标准Java API,您可以使用java.util.Properties:

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

#6


3  

In 19 lines, extending the java.util.Properties to parse into multiple sections:

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

#7


2  

Another option is Apache Commons Config also has a class for loading from INI files. It does have some runtime dependencies, but for INI files it should only require Commons collections, lang, and logging.

另一个选项是Apache Commons Config还有一个用于从INI文件加载的类。它确实有一些运行时依赖项,但对于INI文件,它应该只需要Commons集合,lang和logging。

I've used Commons Config on projects with their properties and XML configurations. It is very easy to use and supports some pretty powerful features.

我在项目及其属性和XML配置上使用了Commons Config。它非常易于使用,并支持一些非常强大的功能。

#8


2  

You could try JINIFile. Is a translation of the TIniFile from Delphi, but for java

你可以试试JINIFile。是来自Delphi的TIniFile的翻译,但是对于java

https://github.com/SubZane/JIniFile

https://github.com/SubZane/JIniFile

#9


1  

I personally prefer Confucious.

我个人更喜欢孔子。

It is nice, as it doesn't require any external dependencies, it's tiny - only 16K, and automatically loads your ini file on initialization. E.g.

这很好,因为它不需要任何外部依赖,它很小 - 只有16K,并在初始化时自动加载你的ini文件。例如。

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

#1


107  

The library I've used is ini4j. It is lightweight and parses the ini files with ease. Also it uses no esoteric dependencies to 10,000 other jar files, as one of the design goals was to use only the standard Java API

我用的库是ini4j。它很轻巧,可以轻松解析ini文件。此外,它不会对10,000个其他jar文件使用深奥的依赖关系,因为其中一个设计目标是仅使用标准Java API

This is an example on how the library is used:

这是关于如何使用库的示例:

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


60  

As mentioned, ini4j can be used to achieve this. Let me show one other example.

如上所述,ini4j可用于实现此目的。让我再举一个例子。

If we have an INI file like this:

如果我们有这样的INI文件:

[header]
key = value

The following should display value to STDOUT:

以下应显示STDOUT的值:

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

Check the tutorials for more examples.

查看教程以获取更多示例。

#3


25  

As simple as 80 lines:

简单到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


15  

Here's a simple, yet powerful example, using the apache class HierarchicalINIConfiguration:

这是一个简单而强大的示例,使用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 has a number of runtime dependencies. At a minimum, commons-lang and commons-logging are required. Depending on what you're doing with it, you may require additional libraries (see previous link for details).

Commons Configuration具有许多运行时依赖性。至少需要公共区域和公共区域记录。根据您正在使用的内容,您可能需要其他库(有关详细信息,请参阅上一个链接)。

#5


12  

Or with standard Java API you can use java.util.Properties:

或者使用标准Java API,您可以使用java.util.Properties:

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

#6


3  

In 19 lines, extending the java.util.Properties to parse into multiple sections:

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

#7


2  

Another option is Apache Commons Config also has a class for loading from INI files. It does have some runtime dependencies, but for INI files it should only require Commons collections, lang, and logging.

另一个选项是Apache Commons Config还有一个用于从INI文件加载的类。它确实有一些运行时依赖项,但对于INI文件,它应该只需要Commons集合,lang和logging。

I've used Commons Config on projects with their properties and XML configurations. It is very easy to use and supports some pretty powerful features.

我在项目及其属性和XML配置上使用了Commons Config。它非常易于使用,并支持一些非常强大的功能。

#8


2  

You could try JINIFile. Is a translation of the TIniFile from Delphi, but for java

你可以试试JINIFile。是来自Delphi的TIniFile的翻译,但是对于java

https://github.com/SubZane/JIniFile

https://github.com/SubZane/JIniFile

#9


1  

I personally prefer Confucious.

我个人更喜欢孔子。

It is nice, as it doesn't require any external dependencies, it's tiny - only 16K, and automatically loads your ini file on initialization. E.g.

这很好,因为它不需要任何外部依赖,它很小 - 只有16K,并在初始化时自动加载你的ini文件。例如。

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