I have a text file imgui.ini containing:
[Debug]
Pos=7,79
Size=507,392
Collapsed=0
[ImGui Demo]
Pos=320,5
Size=550,680
Collapsed=0
The best way to parse such a file (without using dedicated 3rd party libraries), is via the regex API, and its front-end class Scanner. Unfortunately, the best operations to implement it via Stream API, are currently missing. Namely, Matcher.results() and Scanner.findAll(…) are not there yet. So unless we want to wait until Java 9, we have to create similar methods for a Java 8 compatible solution:
public static Stream findAll(Scanner s, Pattern pattern) {
return StreamSupport.stream(new Spliterators.AbstractSpliterator(
1000, Spliterator.ORDERED|Spliterator.NONNULL) {
public boolean tryAdvance(Consumer super MatchResult> action) {
if(s.findWithinHorizon(pattern, 0)!=null) {
action.accept(s.match());
return true;
}
else return false;
}
}, false);
}
public static Stream results(Matcher m) {
return StreamSupport.stream(new Spliterators.AbstractSpliterator(
m.regionEnd()-m.regionStart(), Spliterator.ORDERED|Spliterator.NONNULL) {
public boolean tryAdvance(Consumer super MatchResult> action) {
if(m.find()) {
action.accept(m.toMatchResult());
return true;
}
else return false;
}
}, false);
}
Using methods with a similar semantic allows us to replace their usage with the standard API methods, once Java 9 is released and becomes commonplace.
Using these two operations, you can parse your file using
Pattern groupPattern=Pattern.compile("\\[(.*?)\\]([^\\[]*)");
Pattern attrPattern=Pattern.compile("(.*?)=(.*)\\v");
Map> m;
try(Scanner s=new Scanner(Paths.get(context.io.iniFilename))) {
m = findAll(s, groupPattern).collect(Collectors.toMap(
gm -> gm.group(1),
gm -> results(attrPattern.matcher(gm.group(2)))
.collect(Collectors.toMap(am->am.group(1), am->am.group(2)))));
}
the resulting map m holds all information, mapping from the group names to another map holding the key/value pairs, i.e. you can print an equivalent .ini file using:
m.forEach((group,attr)-> {
System.out.println("["+group+"]");
attr.forEach((key,value)->System.out.println(key+"="+value));
});