2

I have the following Ini-File

[Test]
a=1
b=2
a=3

and I need these key value pairs in the correct order. My problem is, I can find no way to achieve this. I tried the following three options:

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

        }
}

but what I get is:

a = 3
b = 2

a = 1
a = 3
b = 2

b = 2
a = 3

None of this is in the correct Order or contains all values :(

//EDIT: Correct order should be like the ini-File:

a=1
b=2
a=3
DNA
  • 42,007
  • 12
  • 107
  • 146
xani
  • 784
  • 1
  • 7
  • 21
  • 1
    Would you tell us what your "correct order" should look like? – PKlumpp May 20 '14 at 12:18
  • The same order as in the ini-File: a=1, b=2, a=3 – xani May 20 '14 at 12:20
  • 1
    Why would you need this kind of information in a particular order? IMO this is not the point of a `.ini` file. – Joffrey May 20 '14 at 12:33
  • I know that this is not what ini is made for. But I need this for my program to do instructions in the correct order. I could have used an other fileformat. But ini is realy simple and has not to much overhead (like xml) for my purpose. – xani May 20 '14 at 12:38
  • Then you can't use a library that considers it as an ini file. Ini4j will consider it as a 2-level map, and the order won't matter to it. You should parse it your own way. – Joffrey May 20 '14 at 12:39

3 Answers3

2

I think your problem is that Section is implement as a Map an thus its iteration order dependent of its keys hashes and reallocation policies.

Edit:

I have downloaded ini4j source code and found that Section is deffined as:

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

Extending OptionMap interface which extends MultiMap interface:

public interface OptionMap extends MultiMap<String, String>, CommentedMap<String, String>

I found at BasicProfile implementation that the MultiMap implementation used by Ini class (the one retuned by ini.get(sectionName)) is an extension of CommonMultimap class which store its elements in a java.util.SortedMap. That means your keys will be ordered but not with the same order they appear in your file but the one given by java.util.SortedMap.

At Oracle documentation site you can read that:

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

Is:

A Map that further provides a total ordering on its keys. The map is ordered according to the natural ordering of its keys, or by a Comparator typically provided at sorted map creation time. This order is reflected when iterating over the sorted map's collection views (returned by the entrySet, keySet and values methods). Several additional operations are provided to take advantage of the ordering. (This interface is the map analogue of SortedSet.)

Conclusion:

The ini file keys-at-same-level order information is lost in the file objects representation so unless you open the config file as a text file and load a list of key orders you won't be able to reproduce it.

1

IMO, an ini file shouldn't be considered with any particular order. Using Sets should warn you about this (sets are not ordered by default).

There is only a 2-level map: each header being a key, which associated value is in turn a map of key-value pairs. It could be expressed like this:

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

In your specific case, you would have a map like this:

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

That's why you can call it with such a statement (here is the original answer mentioning this):

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

So with such a structure, the original order does not really make sense anymore.

Possible solutions

  • sort the keys: here you won't retrieve the original file order, but you can have AN order.
  • create your own parser: here you're free to parse in the original file order.
Community
  • 1
  • 1
Joffrey
  • 32,348
  • 6
  • 68
  • 100
0

Iteration over section entries, preserving order:

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