我正在编写一个Java的遗留应用程序替代品。其中一个要求是必须将旧应用程序使用的ini文件按原样读入新的Java应用程序中。这些ini文件的格式是常见的Windows格式,包含标题部分和键值对,使用#作为注释字符。
我尝试使用Java的Properties类,但是如果不同标题之间存在名称冲突,那么它当然无法工作。
因此问题是,最简单的方法是什么,以便读取这个INI文件并访问键?
hoat4的解决方案非常优雅和简单。它适用于所有“合理”的ini文件。然而,我看到很多ini文件中的键(key)有未转义的空格字符。
为了解决这个问题,我下载并修改了java.util.Properties
的一个副本。虽然这有点不正规,而且是短期的,但实际的修改只有几行代码,非常简单。我将向JDK社区提出建议,以包含这些更改。
通过添加一个内部类变量:
private boolean _spaceCharOn = false;
我控制与扫描键/值分隔点相关的处理。
我用一个小的私有方法替换了空格字符搜索代码,该方法根据上述变量的状态返回布尔值。
private boolean isSpaceSeparator(char c) {
if (_spaceCharOn) {
return (c == ' ' || c == '\t' || c == '\f');
} else {
return (c == '\t' || c == '\f');
}
}
这个方法在私有方法load0(...)
中使用了两次。
还有一个公共方法可以打开它,但如果空格分隔符对您的应用程序没有问题,最好使用Properties
的原始版本。
如果感兴趣,我愿意发布我的IniFile.java
文件的代码。它可以与Properties
的任何版本一起使用。
通过 @Aerospace 的答案,我意识到 INI 文件可以有没有键值的部分。在这种情况下,应该在找到任何键值之前添加到顶层映射中,例如(针对 Java 8 进行最小更新):
Path location = ...;
try (BufferedReader br = new BufferedReader(new FileReader(location.toFile()))) {
String line;
String section = null;
while ((line = br.readLine()) != null) {
Matcher m = this.section.matcher(line);
if (m.matches()) {
section = m.group(1).trim();
entries.computeIfAbsent(section, k -> new HashMap<>());
} else if (section != null) {
m = keyValue.matcher(line);
if (m.matches()) {
String key = m.group(1).trim();
String value = m.group(2).trim();
entries.get(section).put(key, value);
}
}
}
} catch (IOException ex) {
System.err.println("Failed to read and parse INI file '" + location + "', " + ex.getMessage());
ex.printStackTrace(System.err);
}
这很简单……
//import java.io.FileInputStream;
//import java.io.FileInputStream;
Properties prop = new Properties();
//c:\\myapp\\config.ini is the location of the ini file
//ini file should look like host=localhost
prop.load(new FileInputStream("c:\\myapp\\config.ini"));
String host = prop.getProperty("host");