我有以下Ini-File
[Test]
a=1
b=2
a=3
和我需要这些键值对以正确的顺序。我的问题是,我找不到实现这一点的方法。我尝试了以下三个选项:
Ini ini = new Ini(new File("test.ini"));
for (String sectionName : ini.keySet()) {
Section section = ini.get(sectionName);
//run through keyset
for (String key : section.keySet()) {
System.out.println(key + " = " + section.get(key));
}
System.out.println();
//run through all values
for (String key : section.keySet()) {
List<String> list = section.getAll(key);
for (String value : list) {
System.out.println(key + " = " + value);
}
}
System.out.println();
//run through entries
Set<Entry<String,String>> se = section.entrySet();
for(Entry<String,String> e:se){
System.out.println(e.getKey() + " = " + e.getValue());
}
}
但是我得到的是:
a = 3
b = 2
a = 1
a = 3
b = 2
b = 2
a = 3
这些都不是正确的顺序或包含所有值:(
//编辑:正确的顺序应该是ini-File:
a=1
b=2
a=3
我认为你的问题是Section
是作为Map实现的,因此它的迭代顺序依赖于它的键哈希和重新分配策略。
我已经下载了ini4j源代码,发现Section
被定义为:
interface Section extends OptionMap
{
Section getChild(String key);
String getName();
Section getParent();
String getSimpleName();
Section addChild(String key);
String[] childrenNames();
Section lookup(String... path);
void removeChild(String key);
}
扩展OptionMap
接口,扩展MultiMap
接口:
public interface OptionMap extends MultiMap<String, String>, CommentedMap<String, String>
我发现在BasicProfile
实现中,Ini
类(由ini.get(sectionName)
返回的一个)使用的MultiMap
实现是CommonMultimap
类的扩展,该类将其元素存储在java.util.SortedMap
中。这意味着您的密钥将被排序,但与它们在您的文件中出现的顺序不同,而是由java.util.SortedMap
给出的顺序。
在Oracle文档站点,你可以读到:
public interface SortedMap<K,V> extends Map<K,V>
:
进一步提供键的总排序的Map。映射根据其键的自然顺序排序,或者由通常在排序映射创建时提供的Comparator排序。这个顺序在迭代排序映射的集合视图时反映出来(由entrySet、keySet和values方法返回)。提供了几个额外的操作来利用排序。(此接口是SortedSet的映射模拟)
结论:
ini
文件的同级密钥顺序信息在文件对象表示中丢失,因此除非您将配置文件作为文本文件打开并加载密钥顺序列表,否则您将无法复制它。
在我看来,ini文件不应该有任何特定的顺序。使用Set
s应该警告您这个问题(默认情况下集合不是有序的)。
只有一个2级映射:每个标头是一个键,对应的值依次是键值对的映射。它可以这样表示:
// header key value
Map<String, Map<String, String>>
在您的特定情况下,您将拥有这样的映射:
"Test" ->
"a" -> {"1", "3"}
"b" -> "2"
这就是为什么你可以用这样的语句调用它(这里是提到这一点的原始答案):
Ini ini = new Ini(new File("/path/to/file"));
System.out.println(ini.get("header", "key"));
所以在这样的结构下,原来的顺序就没有意义了。
可能的解决方案- 排序键:这里你不会检索原来的文件顺序,但你可以有一个顺序。
- 创建自己的解析器:在这里你可以自由地按照原始文件顺序进行解析。
遍历section项,保持顺序:
for (String option : section.keySet()) {
int n = section.length(option);
for (int i = 0; i < n; i++) {
// Option name: option
// Option value: section.get(option, i)
// For example,
destinationIni.put(destinationSectionName, option, section.get(option, i));
}
}