ファイルからの入力とファイルへの出力は次のようにします。
import java.io.*;
class Test {
public static void main(String args[]) {
try {
InputStream input
= new FileInputStream("foo.txt"); // 入力ファイルを開く
OutputStream output
= new FileOutputStream("bar.txt"); // 出力ファイルを開く
int c;
while ((c = input.read()) != -1) // 入力
output.write(c); // 出力
input.close(); // 入力ファイルを閉じる
output.close(); // 出力ファイルを閉じる
} catch (IOException e) { // 入出力エラーをつかまえる
System.err.println(e); // エラーメッセージ出力
System.exit(1); // 終了コード 1 で終了する
}
}
}
これは,foo.txt というファイルを読んで, 内容をそのまま bar.txt というファイルに書き出すプログラムです。
もし foo.txt が存在しないと, 15行目の System.err.println(e); が
java.io.FileNotFoundException: foo.txt
と出力して止まってしまいます。
また,もし bar.txt があると,それに上書きしてしまいますので,
気をつけてください。
上のプログラムで,
InputStream input;
input = new FileInputStream("foo.txt");
としていますね。これは本当は
FileInputStream input;
input = new FileInputStream("foo.txt");
と書くべきだと思われるかもしれません。もちろんそう書いてもいいのですが,
FileInputStream は InputStream の子クラスですので,
より一般的な InputStream 型の変数 input を作って,
それに FileInputStream クラスのインスタンスを代入しても
かまわないのです。ただしこれは,
親クラスが子クラスと同じ名前・引数のメソッドを持つ場合だけです。
子クラスの親クラスにない名前のメソッドを使いたい場合は,
ちゃんと子クラスの型の変数に代入しなければなりません。
上のプログラムは,ディスクから1文字(1バイト)ずつ 読み書きしていますので,あまり能率的ではありません。 上の
InputStream input
= new FileInputStream("foo.txt"); // 入力ファイルを開く
OutputStream output
= new FileOutputStream("bar.txt"); // 出力ファイルを開く
のところを
InputStream input
= new BufferedInputStream(
new FileInputStream("foo.txt"));
OutputStream output
= new BufferedOutputStream(
new FileOutputStream("bar.txt"));
とするだけで,ずいぶんプログラムの実行速度が上がります。
これはバッファリングの効果です。
バッファ(buffer)とは一般に「緩衝(かんしょう)装置」つまり 二つのものの間にはさまって衝撃を和らげるもののことです。
ファイルからの入力の場合は, 1バイトずつディスクから読むと時間がかかるので, 一度にたとえば512バイト読み込んでメモリの一部(バッファ)に保存しておき, 2度目からは実際に読むのではなくメモリからコピーしてくることを意味します。
ファイルへの出力も同様で, 最初は実際に書き込まずバッファに保存しておき, たとえば512バイトになると一気に書き出します。
バッファを使うことをバッファリング(buffering)するともいいます。
バッファリングしているときは,最後の文字を書き出したつもりでも, 実際には端数分がメモリに残っています。 この端数分は, 出力ファイルをクローズした(閉じた)時点でディスクに書き込まれます。 つまり,output.close() を実行した時点で書き込まれます。 クローズを忘れると,ファイルが全部書きおわらないうちに終了して しまうことがありますので,必ずオープンしたらクローズする習慣をつけましょう。
上のプログラムをさらに
DataInputStream input
= new DataInputStream(
new BufferedInputStream(
new FileInputStream("foo.txt")));
PrintStream output
= new PrintStream(
new BufferedOutputStream(
new FileOutputStream("bar.txt")));
とすると,入力では readLine(),
出力では println() のような便利なメソッドが使えるようになります。
たとえば
String s;
while ((s = input.readLine()) != null)
output.println(s);
のようなことができます。
readLine() は,ファイルの終わりまで読み尽くした後では,
null という特別な値を返します。これが返ってきたら,
繰返しを終了します。