Java超|ファイル入出力の基本

画面に出すだけで終わらせず、修行記録をファイルに残す。ファイル入出力を理解すると、Javaのプログラムは「その場で動く処理」から「データを未来へ残せる処理」へ進化します。

これまでのJava学習では、画面に文字を表示したり、キーボードから文字列を受け取ったりする処理を学んできました。

たとえば、画面に表示するなら System.out.println を使いました。

System.out.println("修行開始");

また、キーボードから入力を受け取るときには、System.in、InputStreamReader、BufferedReader などを組み合わせました。

これらは、プログラムと外部がやり取りするための大切なしくみです。

ただし、画面に表示した内容やキーボードから受け取った内容は、そのままでは長く残りません。プログラムが終了すれば、表示された内容は流れてしまい、入力されたデータも保存しなければ消えてしまいます。

そこで登場するのが ファイル です。

ファイルを使うと、プログラムの中で扱ったデータを保存できます。保存したデータは、あとで読み返したり、別のプログラムで使ったり、次回の実行時に再利用したりできます。

ドラゴンボール風にたとえると、修行中に口頭で伝えた内容は、時間がたつと忘れられてしまうかもしれません。

しかし、戦士本部の記録室に修行記録として残しておけば、あとから悟空たちの修行内容を確認できます。

Javaのファイル入出力も、それと同じです。

その場で画面に表示するだけではなく、修行記録を training.txt のようなファイルに残すことで、データをあとから使える形にできます。

この記事では、ファイルを使う意味、ファイル出力の流れ、FileWriter、BufferedWriter、PrintWriter の役割、println による書き込み、close の大切さ、IOException への備えまでを、ドラゴンボールの世界観で整理していきます。

ファイルを使う意味

ファイルは、データを保存しておくための場所です。

画面出力は、その場で結果を確認するには便利です。
キーボード入力は、その場でユーザーから情報を受け取るには便利です。

しかし、どちらもそのままではデータを長く残すことには向いていません。

やりたいことファイルが必要になる理由
データをあとで読み返したい画面表示だけでは内容が残らないため
プログラム終了後も内容を残したいメモリ上のデータは基本的に消えるため
大量の情報を保存したいファイルとして外部に保存できるため
別のプログラムでも使いたいファイルなら共有しやすいため
実行記録を残したいログや記録として確認できるため

ドラゴンボール風に言えば、修行場でその場限りの報告をするだけでは、あとから振り返るのが難しくなります。

「今日はどの戦士がどんな修行をしたのか」
「どの技の型を確認したのか」
「どの任務の記録を残したのか」

こうした内容を戦士本部の記録ファイルに書き残しておけば、あとで確認できます。

Javaのファイル出力は、この「記録を残す」処理にあたります。

ファイル入出力もストリームで考える

ファイルを扱うと聞くと、これまでの画面出力やキーボード入力とはまったく違う話に感じるかもしれません。

しかし、Javaではファイルの読み書きも ストリーム の考え方で扱います。

ストリームとは、データの流れです。

処理ストリームでの見方
キーボードから入力する外からプログラムへデータが流れる
画面へ表示するプログラムから画面へデータが流れる
ファイルから読み込むファイルからプログラムへデータが流れる
ファイルへ書き込むプログラムからファイルへデータが流れる

つまり、相手がキーボードでも、画面でも、ファイルでも、データがどちらへ流れるのかに注目すれば、同じ考え方で整理できます。

今回扱うのは、ファイルへの出力です。

プログラムの中にある文字列を、ファイルへ向かう出力ストリームに流して保存します。

ドラゴンボール風に言えば、戦士の修行内容を戦士本部の記録室にあるファイルへ書き込む流れです。

口頭で言うだけではなく、記録係がファイルに書き残すことで、修行結果を未来へ残せます。

ファイルへの出力とは何か

ファイルへの出力とは、プログラムの中にあるデータをファイルへ書き出すことです。

たとえば、文字列を1行ずつファイルへ保存する処理があります。

今回の例では、training.txt というファイルに、戦士本部の修行記録を2行保存します。

処理内容
ファイル名training.txt
書き込む内容修行記録の文字列
書き込み方法println で1行ずつ出力
最後に行うことclose でファイルを閉じる

ファイル出力を使うと、プログラムが終了したあとも、training.txt の中に内容が残ります。

これは、画面出力との大きな違いです。

出力先特徴
画面その場で確認しやすいが、基本的に残らない
ファイルあとから読み返せる形で残せる

ドラゴンボール風にたとえると、画面出力はその場で戦士に伝える口頭連絡です。

ファイル出力は、戦士本部の記録ファイルに正式に残す作業です。

図:ファイル入出力の基本イメージ

この図が示していること

この図では、Javaプログラムの中にある文字列が、training.txt というファイルへ保存される流れを表しています。

画面への出力は、その場で確認するための出力です。
一方、ファイルへの出力は、データを保存してあとから使えるようにするための出力です。

図の要素意味
Javaプログラム修行記録のデータを持っている処理の中心
training.txtデータを保存するファイル
ファイル出力プログラムからファイルへデータを書き込む流れ
System.out画面へ表示する出力

この図から分かることは、ファイル出力は「データを外へ出す」という点では画面出力と似ていますが、保存できるという点が大きく違うということです。

2行を書き込むプログラムで確認する

ここでは、training.txt というファイルへ修行記録を2行書き込むプログラムを見ていきます。

ファイルへ文字列を書き込むために、FileWriter、BufferedWriter、PrintWriter を組み合わせます。

ファイル名:Sample7.java

import java.io.*;

class Sample7
{
    public static void main(String[] args)
    {
        try
        {
            PrintWriter pw = new PrintWriter(
                new BufferedWriter(
                    new FileWriter("training.txt")
                )
            );

            pw.println("悟空:重力修行を開始した");
            pw.println("ベジータ:戦闘フォームの確認を続けている");
            System.out.println("修行記録をファイルに保存しました。");

            pw.close();
        }
        catch(IOException e)
        {
            System.out.println("ファイルの入出力で問題が発生しました。");
        }
    }
}

このプログラムの役割

このプログラムは、training.txt というファイルに文字列を2行書き込みます。

そのあと、画面に保存完了のメッセージを表示します。

処理の流れは、次のようになります。

手順内容
1ファイルに書き込むためのストリームを作る
2println で1行ずつ文字列を書き込む
3保存したことを画面に表示する
4close でファイルを閉じる
5問題が起きたら IOException を catch する

実行後、training.txt には次のような内容が保存されます。

悟空:重力修行を開始した
ベジータ:戦闘フォームの確認を続けている

この内容は画面に表示されるだけではなく、ファイルとして残ります。

そのため、あとから training.txt を開いて確認できます。

ファイル出力のストリームを作る部分

このプログラムで特に大切なのは、次の部分です。

PrintWriter pw = new PrintWriter(
    new BufferedWriter(
        new FileWriter("training.txt")
    )
);

最初に見ると、クラスが何重にも重なっていて少し難しく感じるかもしれません。

しかし、役割を分けると分かりやすくなります。

クラス役割
FileWriterファイルへ文字を書き込むための基本の文字ストリーム
BufferedWriterバッファを使って効率よく書き込む
PrintWriterprintln で1行ずつ書き出しやすくする

つまり、3つのクラスは同じことをしているのではありません。

それぞれが別の役割を持ち、組み合わせることで使いやすいファイル出力を実現しています。

ドラゴンボール風に言えば、記録作業を1人で全部行うのではなく、役割を分担しているイメージです。

Javaのクラスドラゴンボール風の役割
FileWriter記録ファイルを開く係
BufferedWriter書き込む内容を一時的に整理する係
PrintWriter1行ずつ整った形で記録する係

FileWriter の役割

FileWriter は、ファイルへ文字を書き込むための基本となるクラスです。

Sample7.java では、次のように使っています。

new FileWriter("training.txt")

これは、training.txt というファイルへ文字を書き込むための流れを作っています。

部分意味
FileWriterファイルへ文字を書き込むためのクラス
training.txt書き込み先のファイル名
new FileWriter("training.txt")training.txt へ書き込む準備をする

ドラゴンボール風にたとえると、FileWriter は戦士本部の記録ファイルを開く係です。

どのファイルに記録するのかを決めなければ、修行内容を書き込めません。

今回なら、training.txt という記録ファイルを開いて、そこへ文字を書き込めるようにしています。

BufferedWriter の役割

BufferedWriter は、バッファを使って効率よく文字を書き込むためのクラスです。

Sample7.java では、FileWriter を BufferedWriter で包んでいます。

new BufferedWriter(
    new FileWriter("training.txt")
)

バッファとは、データをいったんためておく場所のようなものです。

書き込むたびに細かくファイルへ反映するのではなく、ある程度まとめながら処理することで、効率よく書き込めます。

クラス・用語役割
BufferedWriterバッファを使って効率よく書き込む
バッファデータを一時的にためる場所

ドラゴンボール風に言えば、修行記録を1文字ずつ記録室へ運ぶのではなく、いったんブルマの記録装置にまとめてからファイルへ書き写すようなイメージです。

このひと手間によって、書き込みの流れがスムーズになります。

PrintWriter の役割

PrintWriter は、文字列を出力しやすくするためのクラスです。

特に、println を使って1行ずつ書き込めるのが便利です。

Sample7.java では、BufferedWriter をさらに PrintWriter で包んでいます。

PrintWriter pw = new PrintWriter(
    new BufferedWriter(
        new FileWriter("training.txt")
    )
);

この pw を使って、ファイルへ1行ずつ文字列を書き込めます。

pw.println("悟空:重力修行を開始した");
pw.println("ベジータ:戦闘フォームの確認を続けている");
クラス・メソッド役割
PrintWriter文字列を出力しやすくする
println文字列を書き込み、改行も入れる
pwPrintWriter オブジェクトを指す変数

ドラゴンボール風にたとえると、PrintWriter は記録係です。

修行記録を1項目ずつ整った形でファイルへ書き込んでくれるため、コードも読みやすくなります。

なぜクラスを重ねて使うのか

FileWriter、BufferedWriter、PrintWriter が重なっているのを見ると、最初は複雑に感じるかもしれません。

しかし、これは役割分担です。

1つのクラスだけで全部を担当するのではなく、それぞれの得意な役割を組み合わせています。

組み合わせ役割
FileWriter実際のファイルへ文字を書けるようにする
BufferedWriter効率よく書き込めるようにする
PrintWriterprintln で1行ずつ扱いやすくする

この組み合わせによって、ファイルへ文字を書き込みやすく、効率よく、読みやすい形で出力できます。

ドラゴンボール風に言えば、修行記録を残すときに、次のような役割分担をしているようなものです。

役割担当
記録ファイルを開くFileWriter
記録を一時的に整えるBufferedWriter
1行ずつ記録するPrintWriter

こうして見ると、クラスを重ねている理由がかなり自然に見えてきます。

図:ファイルへ書き込むクラスの流れ

この図が示していること

この図では、Javaプログラムの文字データが、PrintWriter、BufferedWriter、FileWriter を通って training.txt へ保存される流れを表しています。

PrintWriter は、println を使って1行ずつ書き込みやすくします。

BufferedWriter は、バッファを使って効率よく書き込めるようにします。

FileWriter は、実際に training.txt へ文字を書き込むための流れを作ります。

図の要素役割
Javaプログラム書き込みたい文字列を持つ
PrintWriter1行ずつ書き込みやすくする
BufferedWriter効率よく書き込む
FileWriterファイルへ文字を書き込む
training.txt書き込み結果が保存されるファイル

この図から分かることは、ファイル出力では複数のクラスを重ねて使いますが、それぞれが別の役割を持っているということです。

println で1行ずつ書き込む

ファイルへの書き込みは、次の行で行っています。

pw.println("悟空:重力修行を開始した");
pw.println("ベジータ:戦闘フォームの確認を続けている");

println は、文字列を書き込んだあとに改行も入れてくれます。

そのため、2回 println を呼び出すと、ファイルには2行の内容が保存されます。

コードファイルに書かれる内容
pw.println("悟空:重力修行を開始した");悟空:重力修行を開始した
pw.println("ベジータ:戦闘フォームの確認を続けている");ベジータ:戦闘フォームの確認を続けている

training.txt の中身は、次のようになります。

悟空:重力修行を開始した
ベジータ:戦闘フォームの確認を続けている

画面への出力で System.out.println を使っていた感覚に近く、PrintWriter の println も1行ずつ出力できます。

違うのは、出力先です。

出力方法出力先
System.out.println画面
pw.printlnファイル

このように見ると、ファイル出力も「外へデータを出す」という点では画面出力と同じ考え方で理解できます。

close が必要な理由

ファイルを扱うときに、とても大切なのが close です。

Sample7.java では、最後に次のように書いています。

pw.close();

これは、ファイルを閉じる処理です。

ファイルは、開いて書き込むだけで終わりではありません。
最後にきちんと閉じることで、書き込みを完了させ、使っていた資源を解放します。

メソッド役割
closeファイルを閉じて、書き込みを完了させる

close を忘れると、書き込んだ内容が正しく保存されなかったり、ファイルを使いっぱなしにしてしまったりする可能性があります。

ドラゴンボール風に言えば、修行記録を書いたあと、記録ファイルを閉じて本部の記録棚へ戻す作業です。

ファイルに書くだけ書いて、開きっぱなしで端末に残しておくと、記録の管理として不十分です。

Javaのファイル出力でも、書き込みが終わったら close で締めることが大切です。

なぜ try-catch が必要なのか

Sample7.java では、ファイル処理全体を try-catch で囲んでいます。

try
{
    PrintWriter pw = new PrintWriter(
        new BufferedWriter(
            new FileWriter("training.txt")
        )
    );

    pw.println("悟空:重力修行を開始した");
    pw.println("ベジータ:戦闘フォームの確認を続けている");
    System.out.println("修行記録をファイルに保存しました。");

    pw.close();
}
catch(IOException e)
{
    System.out.println("ファイルの入出力で問題が発生しました。");
}

これは、ファイル入出力では IOException が起こる可能性があるからです。

ファイルは、プログラム内部の変数だけを扱う処理とは違います。

外部のファイルや保存先とやり取りするため、問題が起きる可能性があります。

起こりうる問題内容
保存先に問題があるファイルを作成できない場合がある
書き込みに失敗する権限や環境によって書き込めない場合がある
外部資源に依存するファイルシステムの状態に影響される
途中で問題が起きる入出力中に例外が発生する可能性がある

そのため、IOException を catch して、ファイル入出力の問題に備えています。

ドラゴンボール風に言えば、戦士本部の記録室にファイルを保存しようとしても、記録棚が閉まっていたり、保存装置が使えなかったり、記録係が保存できない状況になるかもしれません。

そのような外部とのやり取りに備えるために、try-catch が必要になります。

IOException の役割

IOException は、入出力で問題が起きたときに扱う例外です。

今回のプログラムでは、FileWriter を使ってファイルへ書き込もうとしています。

new FileWriter("training.txt")

このようなファイル操作では、IOException が起きる可能性があります。

例外役割
IOException入出力処理で問題が起きたことを表す

catch では、次のように IOException を受け取ります。

catch(IOException e)
{
    System.out.println("ファイルの入出力で問題が発生しました。");
}

このようにしておくことで、ファイルの入出力で問題が発生したときに、利用者に分かりやすいメッセージを表示できます。

図:ファイル出力とIOExceptionへの備え

この図が示していること

この図では、ファイル出力処理と IOException への備えを表しています。

try ブロックでは、FileWriter、BufferedWriter、PrintWriter を使ってファイルへ文字を書き込み、最後に close でファイルを閉じています。

しかし、ファイルは外部資源なので、書き込み中に問題が起きる可能性があります。

そのため、catch(IOException e) を用意して、入出力の問題を受け止めます。

図の要素意味
try ブロックファイルへ書き込む処理
FileWriterファイルへ文字を書き込む入口
BufferedWriter効率よく書き込むための補助
PrintWriter1行ずつ書き込みやすくする
closeファイルを閉じて保存を完了する
IOExceptionファイル入出力で起こる問題
catch ブロック問題が起きたときの対応

この図から分かることは、ファイル出力では「書く処理」だけでなく、「問題に備える処理」と「最後に閉じる処理」も大切だということです。

ファイル出力と画面出力の共通点

ファイル出力と画面出力は、出力先が違います。

しかし、どちらも プログラムから外へデータを出す という点では同じです。

出力の種類出力先使うもの
画面出力画面System.out
ファイル出力ファイルFileWriter、BufferedWriter、PrintWriter

画面出力では、System.out.println を使って文字列を画面へ送ります。

System.out.println("修行記録をファイルに保存しました。");

ファイル出力では、pw.println を使って文字列をファイルへ送ります。

pw.println("悟空:重力修行を開始した");

どちらも println を使っているため、似た感覚で理解できます。

書き方意味
System.out.println画面へ1行出力する
pw.printlnファイルへ1行出力する

ドラゴンボール風にたとえると、画面出力はその場の掲示板に知らせを出すことです。

ファイル出力は、戦士本部の記録ファイルに正式に残すことです。

出力先は違いますが、「情報を外へ出す」という流れは共通しています。

ファイルを使えるようになると何ができるか

ファイル出力を理解すると、Javaでできることが大きく広がります。

その場で表示するだけのプログラムから、記録を残せるプログラムへ進めるからです。

できること
ログを残す修行の実行記録を保存する
設定を保存する修行レベルや設定値を残す
データをあとで使う次回起動時に前回の内容を読む
大量データを扱う多数の戦士情報を保存する
結果を共有する別の人や別のプログラムでファイルを使う

ドラゴンボール風に言えば、修行内容をその場で話すだけではなく、戦士本部の記録室に残しておくことで、あとから見返したり、次の修行計画に役立てたりできます。

ファイルは、プログラムの結果を未来へつなげるための大切な保存場所です。

ファイル出力で大切なポイント

ファイル出力を学ぶときは、次の点を押さえておくと理解しやすくなります。

ポイント内容
ファイルデータを長く保存するための場所
ファイル出力プログラムのデータをファイルへ書き出すこと
FileWriterファイルへ文字を書き込む基本のストリーム
BufferedWriterバッファを使って効率よく書き込む
PrintWriterprintln で1行ずつ書き出しやすくする
println文字列を書き込み、改行も入れる
closeファイルを閉じて書き込みを完了する
IOExceptionファイル入出力時の問題に備える例外
try-catch入出力の問題を受け止めるためのしくみ

FileWriter、BufferedWriter、PrintWriter が重なっていると、最初は難しく見えるかもしれません。

しかし、それぞれの役割を分けて考えると、とても筋の通った流れです。

FileWriter で保存先のファイルにつなぐ。
BufferedWriter で効率よく書き込めるようにする。
PrintWriter で println を使って1行ずつ書き込む。
最後に close で閉じる。

この流れが分かると、ファイル出力はかなり理解しやすくなります。

Javaのファイル入出力は、データをその場限りにせず、あとから使える形で残すための重要なしくみです。