コース一覧
    Java中級:例外処理とファイル入出力
    ファイルを行単位で読む

    Java中級:例外処理とファイル入出力

    例外処理とファイル入出力を学び、失敗に対応しながらデータを読み書きするプログラムを作れるようにします。

    1
    例外処理
    01. try-catch で例外をつかむ5分
    02. 複数の catch ブロック5分
    03. throws と例外の伝播5分
    04. 独自の例外を作る5分
    05. try-with-resources5分
    06. finally ブロック5分
    07. 例外処理 まとめクイズ5分
    2
    ファイル I/O
    01. Files でファイルに書き込む5分
    02. ファイルを行単位で読む5分
    03. Path でファイルパスを扱う5分
    04. BufferedReader と Stream API5分
    05. ファイルの存在確認と削除5分
    06. ファイル I/O まとめクイズ5分

    ファイルを行単位で読む

    1 行ずつ読むだけなのに、while と null 判定が要る

    ログを 1 行ずつ確かめたい、設定ファイルを上から順に処理したい。やりたいことは「行の並びが欲しい」だけなのに、昔ながらの書き方だと BufferedReader を用意して、readLine() の戻り値を変数に代入しながら null と比べる while を回し、読み終えたら閉じる、という手続きが要りました。本題に入る前の準備がやたらと長いのです。

    Files.readAllLines は、その全部を 1 行にまとめてくれます。渡した Path のファイルを開いて最後まで読み、閉じたうえで List<String> を返します。

    Java

    import java.nio.file.Files;
    import java.nio.file.Path;
    import java.util.List;
    
    public class Demo {
        public static void main(String[] args) throws Exception {
            List<String> lines = Files.readAllLines(Path.of("access.log"));
            System.out.println(lines.size());
    
            for (String line : lines) {
                System.out.println(line);
            }
        }
    }

    各要素に入るのは行の中身だけで、末尾の \n や \r\n は取り除かれています。返ってくるのは見慣れた List なので、size() で行数を数えるのも、for で回すのも、stream() につなぐのも思いのままです。ファイルは戻ってきた時点ですでに閉じられているので、自分で閉じる必要はありません。

    末尾の改行は 1 行として数えない

    行数を数えると、多くの人が「1 行多いはず」「1 行足りない」で止まります。数え方には決まりがあり、最後の改行のうしろは行として数えません。

    • "a\nb\nc" は ["a", "b", "c"] で 3 行
    • "a\nb\n" は ["a", "b"] で 2 行
    • "hello" は ["hello"] で 1 行
    • "\n" は [""] で 1 行

    "a\nb\n" が 2 行なのは、改行を「行の終わりを示す印」として読んでいるからです。最後の \n は 2 行目を閉じただけで、そのうしろに 3 行目が始まっているわけではありません。テキストファイルの末尾に改行を置く習慣は Unix から続くもので、多くのツールがこの数え方で一致しています。

    空のファイルの場合、返るのは null ではなく要素 0 個の List です。if (lines == null) のような身構えは要らず、lines.isEmpty() で判定します。

    Java

    List<String> empty = Files.readAllLines(Path.of("empty.txt"));
    System.out.println(empty.size());      // 0
    System.out.println(empty.isEmpty());   // true
    解説

    文字化けしたときは、まずファイル側の文字コードを疑ってください。引数 1 つの readAllLines は UTF-8 として読むので、Shift_JIS で保存されたファイルを渡すと化けるか、MalformedInputException で落ちます。第 2 引数に Charset を渡せば読み分けられます。

    やってみよう

    Solution.countLines(String content) を完成させます。

    1. 一時ファイルを作り、受け取った content を書き込む
    2. そのファイルを Files.readAllLines で読み返す
    3. 返ってきた List<String> の行数を int として return する
    4. 後始末として一時ファイルを削除する

    一時ファイルの作り方と書き込みは前回のとおりです。countLines("a\nb\n") は 3 ではなく 2、countLines("") は 0 を返します。上の数え方の表と突き合わせながら確かめてください。

    要件

    1. java.nio.file.Files.createTempFile で一時ファイルを作成し、その Path を使うこと
    2. Files.writeString(path, content) で引数の文字列を書き込み、Files.readAllLines(path) で読み返すこと
    3. 読み返した List<String> の size() を int として return すること (Files.lines(p).count() を使う場合は (int) でキャストする)

    ヒント

    `Files.createTempFile("demo", ".txt")` は接頭辞と拡張子だけ指定すれば、衝突しないユニークなパスを自動で作ってくれます

    `Files.readAllLines` は末尾改行を行として数えないため、`"a\nb\n"` の `size()` は `2` です。テストの期待値もこの仕様に合わせています

    メソッドシグネチャに `throws Exception` を付けておけば `IOException` を個別に `try-catch` しなくても呼び出せます

    生田 陸人
    監修生田 陸人
    ゆめさくエンジニア / 現役ソフトウェアエンジニア監修者プロフィールを見る →
    編集 ゆめさく編集部·公開 2026/05/19·更新 2026/08/26

    関連レッスン

    • Path でファイルパスを扱う

      java.nio.file.Path と Paths.get を使って、OS 非依存にファイルパスを組み立てたり分解したりする基本を学ぶ。

    • BufferedReader と Stream API

      BufferedReader の発想を引き継ぎつつ、Files.lines で 1 行ずつ Stream<String> としてファイルを読み込み、Stream API で集計するモダンな書き方を学ぼう。

    • ファイルの存在確認と削除

      Files.exists / Files.delete などの基本 API を使い、一時ファイルを作って存在を確認し、削除してからもう一度確認するコードを書いてみよう。

    • ファイル I/O まとめクイズ

      ファイル I/O 章 (Files / Path / BufferedReader / try-with-resources) の総まとめ。書き込み API の使い分け、リソースの自動 close、文字コード、例外処理の組み合わせを 4 択クイズで再確認する。

    このレッスンに出てくる用語

    意味があいまいなまま進んだ語は、ここから読み直せます。

    • 処理計算や代入を表す長方形
    • 戻り値呼び出し元への返答を表す点線矢印
    • 変数データに名前をつけて参照する仕組み
    • 文字化け送受信側のエンコード不一致による表示崩れ
    • 文字コード文字に番号を割り当てるルール体系
    • 引数位置引数=順番で渡す。
    • instanceof「このオブジェクトの実際の型は何か」を確認 → 安全に変換
    main.java
    エディタを読み込んでいます

    メモ

    ファイルを行単位で読む

    ⌘S で保存