从ini文件中读取多个值,保持顺序



我有以下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));
    }
}

相关内容

  • 没有找到相关文章

最新更新