Java 逆引き集 | ファイルの行ストリーム処理(Files.lines) — 大規模ファイル処理

Java Java
スポンサーリンク

ファイルの行ストリーム処理(Files.lines) — 大規模ファイル処理

Java NIO の Files.lines(Path) は、テキストファイルを 1行ずつストリームとして処理できる便利なメソッドです。大規模ファイルでも全体を一度に読み込まず、遅延読み込みで効率的に扱えるのが特徴です。


基本の仕組み

  • 戻り値: Stream<String> (各要素が1行の文字列)
  • 遅延読み込み: 必要な行だけ逐次読み込むため、大きなファイルでもメモリ効率が良い。
  • 注意点: ストリームは I/O リソースを持つので、必ず try-with-resources で閉じる。

基本コード例

ファイルを1行ずつ出力

import java.nio.file.*;
import java.io.IOException;
import java.util.stream.Stream;

public class FileLinesBasic {
    public static void main(String[] args) throws IOException {
        Path path = Paths.get("data.txt");

        try (Stream<String> lines = Files.lines(path)) {
            lines.forEach(System.out::println);
        }
    }
}
Java
  • ポイント: try-with-resources で自動的にストリームを閉じる。

フィルタして処理

Path path = Paths.get("data.txt");

try (Stream<String> lines = Files.lines(path)) {
    lines.filter(l -> l.contains("ERROR"))
         .forEach(System.out::println);
}
Java
  • ポイント: ログファイルから「ERROR」を含む行だけ抽出。

map を使って変換

try (Stream<String> lines = Files.lines(Paths.get("numbers.txt"))) {
    int sum = lines.mapToInt(Integer::parseInt).sum();
    System.out.println("合計=" + sum);
}
Java
  • ポイント: 数字が並んだファイルを読み込み、合計を計算。

例題で理解する

例題1: 大規模ログから統計を取る

Path logFile = Paths.get("server.log");

try (Stream<String> lines = Files.lines(logFile)) {
    long errorCount = lines.filter(l -> l.contains("ERROR")).count();
    System.out.println("ERROR件数=" + errorCount);
}
Java
  • 用途: 数百万行のログでもメモリに全部載せずに処理可能。

例題2: CSV ファイルから特定列を抽出

Path csv = Paths.get("users.csv");

try (Stream<String> lines = Files.lines(csv)) {
    lines.map(l -> l.split(","))
         .map(cols -> cols[1]) // 2列目(名前)
         .forEach(System.out::println);
}
Java
  • 用途: 大規模 CSV から必要な列だけ取り出す。

例題3: ファイルからユニークな単語を抽出

Path text = Paths.get("book.txt");

try (Stream<String> lines = Files.lines(text)) {
    lines.flatMap(l -> Arrays.stream(l.split("\\s+")))
         .map(String::toLowerCase)
         .distinct()
         .sorted()
         .forEach(System.out::println);
}
Java
  • 用途: 書籍テキストからユニークな単語リストを作成。

テンプレート集

  • 基本読み込み
try (Stream<String> lines = Files.lines(Paths.get("file.txt"))) {
    lines.forEach(System.out::println);
}
Java
  • フィルタ+件数
long count = Files.lines(Paths.get("file.txt"))
                  .filter(s -> 条件)
                  .count();
Java
  • map で変換
List<Integer> nums = Files.lines(Paths.get("file.txt"))
                          .map(Integer::parseInt)
                          .toList();
Java
  • flatMap で単語展開
Files.lines(Paths.get("file.txt"))
     .flatMap(line -> Arrays.stream(line.split("\\s+")))
     .forEach(System.out::println);
Java

落とし穴と回避策

  • リソース管理: Files.lines はファイルを開いたままなので、必ず try-with-resources で閉じる。
  • 文字コード: デフォルトは UTF-8。別の文字コードなら Files.lines(path, charset) を使う。
  • 大規模ファイル: 全行を collect(toList()) するとメモリに載ってしまう。逐次処理(forEach, count, sum)で流すのが安全。
  • 例外処理: IOException が発生する可能性があるので、throws か try-catch を必ず書く。

まとめ

  • Files.lines は「大規模ファイルを1行ずつストリーム処理」するための定番。
  • フィルタ・map・flatMap と組み合わせると、ログ解析や CSV 処理が簡潔に書ける。
  • try-with-resources で安全に閉じること、メモリに全行をため込まないことが重要。

👉 練習課題: 「数百万行のログファイルから、ERROR を含む行を抽出して件数を数える」コードを書いてみると、Files.lines の強みが体感できます。

タイトルとURLをコピーしました