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

Mar*_*gón 100 java ini parsing

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

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

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

Mar*_*gón 117

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

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

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));
Run Code Online (Sandbox Code Playgroud)

  • 不起作用,错误说"IniFile无法解析为某种类型" (2认同)
  • 即使他们再次更改类名,http://ini4j.sourceforge.net/tutorial/OneMinuteTutorial.java.html也可能保持最新状态. (2认同)
  • 使用这个解决方案失败了,浪费了我很多时间。这是越野车。该项目最后一次更新是在 2015 年,许多 3 年前记录的门票仍然开放。对我来说没有任何作用。我尝试过 WINI、prefs.node 和许多其他的变体,但都失败了。最好使用维护良好的代码。 (2认同)

tsh*_*ang 63

正如提到的,ini4j可以用来实现这一目标.让我再举一个例子.

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

[header]
key = value
Run Code Online (Sandbox Code Playgroud)

以下应显示value给STDOUT:

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

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

  • 整齐!我一直在使用BufferedReader和一些复制/粘贴字符串解析代码,而不必为我的应用程序添加另一个依赖项(当你开始添加第三方API时,即使是最简单的任务,也可能会超出比例).但我不能忽视这种简单性. (2认同)

Aer*_*ace 28

简单到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 ));
   }
}
Run Code Online (Sandbox Code Playgroud)

  • 不要重新发明轮子。这是一个标准问题,因为它得到了建议,在每个需要解决它的代码库中维护其解决方案,而不是构建和使用公共库是反进步的。 (2认同)

小智 16

这是一个简单但功能强大的示例,使用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");
}
Run Code Online (Sandbox Code Playgroud)

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


Pet*_*ter 13

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

Properties props = new Properties();
try (FileInputStream in = new FileInputStream(path)) {
    props.load(in);
}
Run Code Online (Sandbox Code Playgroud)

  • 问题是,对于ini文件,结构有标题.Property类不知道如何处理标题,可能存在名称冲突 (11认同)
  • 简单的解决方案+1,但只适合简单的配置文件,正如Mario Ortegon和rds注意到的那样. (3认同)
  • 此外,`Properties`类没有正确获取包含\的值 (2认同)

hoa*_*at4 10

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

    }.load(reader);
    return result;
}
Run Code Online (Sandbox Code Playgroud)