第10回 では継承とインターフェースを学びました。今回は 「ファイル入出力(I/O)」 を学びます。
ここまでのプログラムは、実行が終わると結果が消えていました。今回学ぶ ファイル入出力 を覚えると、プログラムの結果をファイルに保存したり、外部ファイルからデータを読み込んだりできるようになります。実務でも CSV 処理・ログ出力・設定ファイル読み込みなど、超頻出のテーマです。
この記事のゴール
「テキストファイルを 1 行ずつ読み込む」「テキストファイルに書き込む」「try-with-resources でリソースを安全に閉じる」が書けるようになることです。
ファイル I/O の全体像
Java でのファイル操作は、「① ファイルを開く → ② 読み書きする → ③ ファイルを閉じる」 の 3 ステップが基本です。
⚠ 超重要: ファイルは使い終わったら 必ず閉じること。閉じ忘れると 「ファイルロック」 などのトラブルになります。 Java 7 以降の
try-with-resourcesを使うと、自動的に閉じてくれるので、これを使えば安心です。
ファイルの書き込み(FileWriter)
まずは「文字を 1 つのファイルに書き出す」シンプルな例から見てみましょう。
import java.io.FileWriter; // ファイルに書き出す部品
import java.io.IOException; // ファイル操作で発生する例外
public class WriteFileDemo {
public static void main(String[] args) {
// try-with-resources: try() の中で開いたものは自動で close() される
try (FileWriter writer = new FileWriter("output.txt")) {
// .write() でファイルに文字列を書き込む
writer.write("こんにちは、Java!\n"); // \n は改行
writer.write("ファイル書き込みのテストです。\n");
System.out.println("書き込み完了!");
} catch (IOException e) { // 書き込み失敗時の処理
System.out.println("エラー: " + e.getMessage());
}
}
}
実行すると、プロジェクトの直下に output.txt が作られ、テキストが書き込まれます。
コード解説
| 部分 | 意味 |
|---|---|
import java.io.FileWriter; | ファイル書き込み用のクラスを取り込む |
new FileWriter("output.txt") | output.txt を「書き込みモード」で開く |
try (...) | try-with-resources 構文。括弧内のリソースは自動で閉じられる |
writer.write("...") | 文字列をファイルに書き込む |
\n | 改行文字(Windows なら \r\n でも OK) |
catch (IOException e) | ファイル操作中の例外をキャッチ(第 8 回参照) |
💡
new FileWriter("output.txt", true)のように 第 2 引数にtrueを渡すと、既存ファイルに追記(append)モードになります。デフォルトは上書きです。
ファイルの読み込み(Scanner)
第 8 回でキーボード入力に使った Scanner は、実はファイル読み込みにも使えます。
import java.io.File; // ファイルを表す部品
import java.io.FileNotFoundException; // ファイルが見つからない例外
import java.util.Scanner; // 読み込み部品
public class ReadFileDemo {
public static void main(String[] args) {
File file = new File("output.txt"); // 読みたいファイルを指定
// try-with-resources で Scanner を自動 close
try (Scanner sc = new Scanner(file)) {
// 1 行ずつ読み込む(行があるうちは続ける)
while (sc.hasNextLine()) { // 次の行があるか?
String line = sc.nextLine(); // 1 行読む
System.out.println(line); // コンソールに出力
}
} catch (FileNotFoundException e) { // ファイルが無いと例外
System.out.println("ファイルが見つかりません: " + e.getMessage());
}
}
}
実行すると、output.txt の中身が 1 行ずつコンソールに表示されます。
重要メソッド: hasNextLine() と nextLine()
hasNextLine(): 次に読める行があるか? を返す(true / false)nextLine(): 1 行読み込んで文字列で返す(改行は含まない)
この組み合わせが 「ファイルを最後まで 1 行ずつ読む」 定石パターンです。
try-with-resources の何が嬉しい?
「try() の中でファイルを開けば、自動で閉じてくれる」── これがどれだけ便利か、昔の書き方と比較してみましょう。
昔の書き方(Java 6 以前・冗長)
FileWriter writer = null;
try {
writer = new FileWriter("output.txt");
writer.write("Hello\n");
} catch (IOException e) {
e.printStackTrace();
} finally {
if (writer != null) {
try {
writer.close(); // 閉じる処理も例外を投げる可能性あり…
} catch (IOException e) {
e.printStackTrace();
}
}
}
今の書き方(try-with-resources・スッキリ)
try (FileWriter writer = new FileWriter("output.txt")) {
writer.write("Hello\n");
} catch (IOException e) {
e.printStackTrace();
}
// close() は不要!自動でやってくれる
6 行 → 1 行 に短縮。さらに 閉じ忘れの心配がない。実務では 必ず try-with-resources を使いましょう。
💡 条件: try-with-resources で扱えるのは
AutoCloseableインターフェースを実装したクラスだけ。FileWriter・Scanner・BufferedReaderなどは全部対応しています。
PrintWriter で快適に書き込む
FileWriter の書き込みは \n を手動で書く必要がありますが、PrintWriter を使うと println()(自動改行) や printf() が使えて便利です。
import java.io.PrintWriter;
import java.io.IOException;
public class PrintWriterDemo {
public static void main(String[] args) {
try (PrintWriter pw = new PrintWriter("scores.txt")) {
pw.println("佐藤,80"); // println で自動改行
pw.println("田中,75");
pw.println("鈴木,90");
pw.printf("平均: %.1f%n", 81.7); // printf で書式指定(%n は OS 別の改行)
} catch (IOException e) {
e.printStackTrace();
}
}
}
生成される scores.txt の内容:
佐藤,80
田中,75
鈴木,90
平均: 81.7
ファイル存在チェック
開く前に「ファイルが本当にあるか?」を確認したいときは、File クラスのメソッドを使います。
import java.io.File;
File file = new File("scores.txt");
if (file.exists()) { // ファイルが存在するか?
System.out.println("ファイルあり!");
System.out.println("サイズ: " + file.length() + " バイト");
System.out.println("読めるか? " + file.canRead());
System.out.println("書けるか? " + file.canWrite());
} else {
System.out.println("ファイルがありません");
}
CSV を読み込む実用例
カンマ区切り(CSV)ファイルから読み込んで処理する、実用的な例です。
入力: scores.csv
佐藤,80
田中,75
鈴木,90
コード:
import java.io.File;
import java.io.FileNotFoundException;
import java.util.Scanner;
public class CsvReadDemo {
public static void main(String[] args) {
File file = new File("scores.csv");
try (Scanner sc = new Scanner(file)) {
int total = 0;
int count = 0;
while (sc.hasNextLine()) {
String line = sc.nextLine(); // 例: "佐藤,80"
// カンマで分割 → ["佐藤", "80"]
String[] parts = line.split(",");
String name = parts[0]; // 名前
int score = Integer.parseInt(parts[1]); // 点数(文字列→整数に変換)
System.out.println(name + "さん: " + score + "点");
total += score; // 合計に加算
count++;
}
// 平均を計算して表示(0 除算回避のため count > 0 をチェック)
if (count > 0) {
System.out.println("平均: " + (total / count));
}
} catch (FileNotFoundException e) {
System.out.println("scores.csv が見つかりません");
}
}
}
編集部より
CSV 読み込みは 実務でも本当によく使うパターンです。ログ集計、データ加工、レポート生成など、応用範囲が広いので、ぜひ手を動かして練習してみてください。
ハマりがちなエラー
エラー① FileNotFoundException
java.io.FileNotFoundException: scores.csv (指定されたファイルが見つかりません。)
原因: ファイルがプログラムの 「カレントディレクトリ」 にないことが多い。 対処:
- ファイルを プロジェクトの直下(IntelliJ なら最上位フォルダ)に置く
- もしくは 絶対パスを指定する:
new File("C:/Users/.../scores.csv")
エラー② 文字化け
原因: ファイルの文字コードと Java の読み込みコードが違う(よくあるのは UTF-8 vs Shift-JIS)。 対処: 文字コードを明示的に指定。
import java.nio.charset.StandardCharsets;
Scanner sc = new Scanner(file, StandardCharsets.UTF_8); // UTF-8 で読み込む
エラー③ ループが終わらない / 1 行抜ける
原因: hasNextLine() を使わず nextLine() だけで while を書くと、ファイル末尾で例外発生。
対処: 必ず while (sc.hasNextLine()) で囲む。
練習問題
names.txt に書かれている名前のリストを読み込んで、1 行ずつ「○○さん、こんにちは!」と表示するプログラムを書いてください。
入力: names.txt
佐藤
田中
鈴木
解答例
import java.io.File;
import java.io.FileNotFoundException;
import java.util.Scanner;
public class GreetFromFile {
public static void main(String[] args) {
File file = new File("names.txt");
try (Scanner sc = new Scanner(file)) {
// ファイルの終わりまで 1 行ずつ読む
while (sc.hasNextLine()) {
String name = sc.nextLine(); // 1 行読み込み
System.out.println(name + "さん、こんにちは!"); // 挨拶
}
} catch (FileNotFoundException e) {
System.out.println("names.txt が見つかりません");
}
}
}
実行結果:
佐藤さん、こんにちは!
田中さん、こんにちは!
鈴木さん、こんにちは!
まとめ
第 11 回では、以下を学びました。
- ✅ FileWriter / PrintWriter でファイル書き込み
- ✅ Scanner + File でファイル読み込み
- ✅
hasNextLine()+nextLine()で 1 行ずつ読むのが定石 - ✅ try-with-resources でファイルを自動 close
- ✅
File.exists()などで事前チェック - ✅ CSV 処理など、実務でも頻出のパターン
次回は 「マルチスレッド入門」 を学びます。Thread / Runnable を使って、複数の処理を同時に動かす仕組みを学びます。お楽しみに!