今までターミナルまたはプロンプトと呼ばれる標準入出力を使って情報のやり取りをしました。今度はコンピューター上に置いたファイルから文字列を読んだりファイルへ書き出したりすることにします。
標準入力とファイル入力の比較
まずファイルから文字を読み込むことにします。ところで以前に標準入力から入力を受け取るためのクラスは以下のように作っていました。
BufferedReader bufReader = new BufferedReader(new InputStreamReader(System.in));
今回もこのBufferedReaderクラスを使うことにします。前回はBufferedReaderを作成するときのパラメータにInputStreamReaderというクラスを使っていましたが今回はFileReaderクラスを使います。~Readerという名前のクラスがたくさん出て来たので一旦整理します。
Object | Reader | InputStreamReader | FileReader |
BufferedReader |
上の図で左のほうが継承元、右のほうが継承先になります。全てのクラスの元はObjectというクラスになります。これはJavaの仕様になっていて特にextendsで継承元を指定しない場合はデフォルトでObjectを継承元と解釈されます。Readerは抽象クラスで継承先のサブクラスで実装が記述されています。InputStreamReaderとBufferedReaderが直接の継承先になっています。FileReaderはこのInputStreamReaderを継承して実装されています。なので抽象クラスのReaderから見ると孫に当たります。
BufferedReaderはインスタンスを作るときにReaderクラスを指定しています。
BufferedReader(Reader in)
これは継承元がReaderクラスであればこのインスタンスの引数として使えることになります。これは直接の継承元でなくても継承元の継承元や、さらにその継承元であっても構いません、とにかくどこかでReaderクラスを継承していればよいのです。
BufferedReaderは以前標準入力で使ったクラスと同じです。ファイル入力であろうが標準入力であろうが一度同じクラスのインスタンスにしてしまえば同じように扱えます。
さてFileReaderはファイルのパスを引数で持つのでコンストラクタは以下のようになります。
BufferedReader bufReader = new BufferedReader(new FileReader("/Users/myaccount/haiku.txt"));
上のパスはMacのものですがWindowsであれば
"C://Users/myaccount/haiku.txt"
のような形になります。ここで書いたディレクトリにhaiku.txtを置きます。ファイルの中身は俳句を三句、三行に分けて描きました。
import java.io.BufferedReader; import java.io.FileNotFoundException; import java.io.FileReader; import java.io.IOException; public class FileTest { public static void main(String[] args) throws FileNotFoundException, IOException{ BufferedReader reader = new BufferedReader(new FileReader("/Users/myaccount/haiku.txt")); while(reader.ready()){ System.out.println(reader.readLine()); } reader.close(); } }
次の行があるかを判定するにはreadyメソッドを使います。BufferedReaderはあらかじめ先読みしてバッファリングしているので次の行が存在するかも自分でわかるようになっています。また読み終わったときにはcloseメソッドを呼び出してファイル入力を閉じるようにしましょう。何もしなくてもプログラムが終了すれば閉じますが複数の入出力を扱う場合はどれを開いてどれを閉じたかは意図的にわかるようにしておくと混乱が無くなります。
出力結果です。ファイルの中身が3行出力されました。
秋深き 隣は何を する人ぞ 朝顔に つるべとられて もらい水 柿くえば 鐘がなるなり 法隆寺