2

我有以下 Ini 文件

[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文件:

a=1
b=2
a=3
4

3 回答 3

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使用的实现(由 重新调整的实现)是类的扩展,它将其元素存储在. 这意味着您的密钥将被排序,但与它们在文件中出现的顺序不同,而是由.Iniini.get(sectionName)CommonMultimapjava.util.SortedMapjava.util.SortedMap

Oracle 文档站点,您可以阅读:

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

是:

进一步提供对其键的总排序的 Map。地图是根据其键的自然顺序排序的,或者由通常在排序地图创建时提供的比较器排序。此顺序在遍历已排序地图的集合视图(由 entrySet、keySet 和 values 方法返回)时反映出来。提供了几个额外的操作来利用排序。(此接口是 SortedSet 的映射类似物。)

结论:

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

于 2014-05-20T12:22:06.453 回答
1

IMO,不应以任何特定顺序考虑 ini 文件。使用Sets 应该警告您这一点(默认情况下不订购集合)。

只有一个 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"));

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

可能的解决方案

  • 对键进行排序:在这里您不会检索原始文件顺序,但您可以有一个顺序。
  • 创建自己的解析器:在这里您可以自由地按原始文件顺序进行解析。
于 2014-05-20T12:42:22.357 回答
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));
    }
}
于 2019-10-21T12:35:28.487 回答