The best way to parse such a file (without using dedicated third-party libraries) is through the regex API and its external Scanner class. Unfortunately, the best operations for its implementation through the Stream API are currently missing. Namely, Matcher.results() and Scanner.findAll(…) do not exist yet. Therefore, if we do not want to wait for Java 9, we must create similar methods for the Java 8-compatible solution:
public static Stream<MatchResult> findAll(Scanner s, Pattern pattern) { return StreamSupport.stream(new Spliterators.AbstractSpliterator<MatchResult>( 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<MatchResult> results(Matcher m) { return StreamSupport.stream(new Spliterators.AbstractSpliterator<MatchResult>( 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 similar semantics allows you to replace their use with standard API methods as soon as 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<String, Map<String, String>> 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 contains all the information, matching from group names to another map containing key / value pairs, i.e. you can print the equivalent .ini file using:
m.forEach((group,attr)-> { System.out.println("["+group+"]"); attr.forEach((key,value)->System.out.println(key+"="+value)); });
source share