我正在编写一个Java的遗留应用程序替代品。其中一个要求是必须将旧应用程序使用的ini文件按原样读入新的Java应用程序中。这些ini文件的格式是常见的Windows格式,包含标题部分和键值对,使用#作为注释字符。
我尝试使用Java的Properties类,但是如果不同标题之间存在名称冲突,那么它当然无法工作。
因此问题是,最简单的方法是什么,以便读取这个INI文件并访问键?
我使用的库是ini4j。它轻量级且易于解析ini文件。此外,它不使用奇怪的依赖关系来连接其他1万个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));
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有一些运行时依赖项。最少需要commons-lang和commons-logging。根据你的使用情况,可能需要其他库(详见上面的链接)。
iniConfObj
,而不是 iniObj
。 - Jean Spector或者您可以使用标准的Java API java.util.Properties:
Properties props = new Properties();
try (FileInputStream in = new FileInputStream(path)) {
props.load(in);
}
native2ascii
)。 - n611x007使用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;
}
Configurable config = Configuration.getInstance();
String host = config.getStringValue("host");
int port = config.getIntValue("port");
new Connection(host, port);
你可以使用ini4j将INI文件转换为Properties格式
Properties properties = new Properties();
Ini ini = new Ini(new File("path/to/file"));
ini.forEach((header, map) -> {
map.forEach((subKey, value) -> {
StringBuilder key = new StringBuilder(header);
key.append("." + subKey);
properties.put(key.toString(), value);
});
});
IniFile
类已经被移除了,可以尝试使用Ini ini = new Ini(new File("/path/to/file"));
。 - Mehdi Karamoslyprefs.node("something").get("val", null)
并没有按照我预期的方式工作。 - Agi Hammerthief