我正在为Java中的遗留应用程序编写替代品.其中一个要求是旧应用程序使用的ini文件必须按原样读入新的Java应用程序.此ini文件的格式是常见的Windows样式,带有标题部分和键=值对,使用#作为注释字符.
我尝试使用Java中的Properties类,但是如果不同标头之间存在名称冲突,那么这当然不起作用.
所以问题是,读取这个INI文件并访问密钥的最简单方法是什么?
我用的库是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));
正如提到的,ini4j可以用来实现这一目标.让我再举一个例子.
如果我们有这样的INI文件:
[header] key = value
以下应显示value
给STDOUT:
Ini ini = new Ini(new File("/path/to/file")); System.out.println(ini.get("header", "key"));
查看教程以获取更多示例.
简单到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 )); } }
这是一个简单但功能强大的示例,使用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具有许多运行时依赖性.至少需要公共区域和公共区域记录.根据您正在使用的内容,您可能需要其他库(有关详细信息,请参阅上一个链接).
或者使用标准Java API,您可以使用java.util.Properties:
Properties props = new Properties(); try (FileInputStream in = new FileInputStream(path)) { props.load(in); }
在18行中,将java.util.Properties
解析扩展为多个部分:
public static MapparseINI(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("]")) return result.put(header.substring(1, header.length() - 1), section = new Properties()); else return section.put(key, value); } }.load(reader); return result; }