Java 8のラムダ式とStreamを使ってINIファイルをパースする
Java 8 で追加されたラムダ式と Stream を使い、Windows のINIファイルをパースするコードを書いたので共有しておきます。
- INIファイルのセクションは無視する仕様
- お尻のホワイトスペースはカットする仕様
ですので、ちゃんとしたい人は Apache Commons Configuration とかを使ってください。
プログラム構造的には、CSV をパースするときの参考にもなると思います。
import java.io.File; import java.io.IOException; import java.nio.charset.Charset; import java.nio.file.Files; import java.nio.file.Paths; import java.util.Properties; import java.util.stream.Stream; public class IniFileToProperties { public static Properties load(String filePath, Charset charset) throws IOException { Properties properties = new Properties(); try (Stream stream = Files.lines(Paths.get(filePath), charset)) { // close処理は不要 stream.forEach(line -> { // 行前後の空白を削除 String trimmedLine = line.trim(); // 空行は無視 if (trimmedLine.isEmpty()) { return; } // コメント行は無視 if (trimmedLine.substring(0,1).equals(";")) { return; } // セクション行も無視 if (trimmedLine.substring(0,1).equals("[")) { return; } // 行の現れる最初の"="でパース int p = trimmedLine.indexOf("="); // "=" が無い場合は無視 if (p == -1) { return; } // properties構築 properties.setProperty(trimmedLine.substring( 0, p ), trimmedLine.substring( p + 1 )); }); } catch (IOException e) { e.printStackTrace(); } finally { } return properties; } }
呼び出し側は↓こんな感じ。
Properties settings = IniFileToProperties.load("C:\\where\to\ini_file.ini", Charset.forName("SJIS")); String baseDir = settings.getProperty("base_dir");
なんだか Java っぽくない Scala 的な書き方で、スッキリしてますね。
ポイントを挙げるなら、多分、以下の2点。
- for 構文でいう continue に近い動きをするには、Stream.forEach に与えるラムダ式で return すればよい。(break相当の機能は無い)
- ローカル変数のスコープ内にあるラムダ式の無名クラスからは、そのローカル変数へアクセスできる。(この場合、無名 Consumer クラスから直接 properties へアクセスし、結果を出力している。)
前者はただのTIPSですが、後者はJava的な考え方が染み付いていて、かつ、ラムダ式の中身が無名クラスだと分かっているほど、気が付くのに時間が掛かりそうだと感じました。
今どきINIファイルなんか読まねーよ。という人は多いと思いますが、ラムダ式とStreamのサンプルコードとしてこのくらいの複雑度のものがあれば、そこから発展させやすいよね。と思ったので、載せておきました。いじょ。