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

时间:2014-05-20 12:16:10

标签: java ini4j

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

3 个答案:

答案 0 :(得分:2)

我认为你的问题是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实施时发现,MultiMap类使用的Ini实现(由ini.get(sectionName)重新调整的实现)是CommonMultimap类的扩展,将其元素存储在java.util.SortedMap中。这意味着您的密钥将被订购,但不会与您在文件中显示的顺序相同,而是java.util.SortedMap给出的顺序。

Oracle documentation site,您可以阅读:

public interface SortedMap<K,V> extends Map<K,V>

时:

一个地图,进一步提供其键的总排序。地图是根据其键的自然顺序排序的,或者是通常在排序地图创建时提供的比较器。迭代有序映射的集合视图(由entrySet,keySet和values方法返回)时会反映此顺序。提供了几个额外的操作以利用订购。 (此界面是SortedSet的地图模拟。)

<强>结论:

ini文件键同级别订单信息在文件对象表示中丢失,因此除非您将配置文件作为文本文件打开并加载关键订单列表,否则您将无法重现它。

答案 1 :(得分:1)

IMO,不应将任何特定订单视为ini文件。使用Set s应警告您(默认情况下不会对集合进行排序)。

只有一个2级地图:每个标题都是一个键,相关的值又是一个键值对的映射。它可以这样表达:

//  header       key    value
Map<String, Map<String, String>>

在您的具体情况下,您将拥有如下地图:

"Test" ->
    "a" -> {"1", "3"}
    "b" -> "2"

这就是为什么你可以用这样的声明(here is the original answer mentioning this)来调用它:

Ini ini = new Ini(new File("/path/to/file"));
System.out.println(ini.get("header", "key"));

所以有了这样的结构,原来的顺序就不再有意义了。

可能的解决方案

  • 对键进行排序:此处您不会检索原始文件顺序,但您可以获得AN订单。
  • 创建自己的解析器:在这里,您可以自由解析原始文件顺序。

答案 2 :(得分:0)

对节条目进行迭代,保留顺序:

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));
    }
}