Revised: May/5th/2002; Since: Jan./5th/2002
ファイルに対するストリームは、次のクラスのオブジェクトとして作ります:
| テキスト・ファイル |
FileReaderFileWriter
|
|---|---|
| バイナリ・ファイル |
FileInputStreamFileOutputStream
|
これらのクラスでは、 JavaVM が動作しているネイティブなファイルシステム上にあるファイルに対するストリームを作ります。このファイルは、 File クラスや FileDescriptor クラスのオブジェクトとして参照します。
継承関係:
java.io.FileReader |
java.io.FileWriter |
|---|---|
java.lang.Object
|
+--java.io.Reader
|
+--java.io.InputStreamReader
|
+--java.io.FileReader
|
java.lang.Object
|
+--java.io.Writer
|
+--java.io.OutputStreamWriter
|
+--java.io.FileWriter
|
コンストラクタ:
FileReader(File file) FileReader(FileDescriptor fd) FileReader(String fileName) FileWriter(File file) FileWriter(FileDescriptor fd) FileWriter(String fileName) FileWriter(String fileName, boolean append)
FileWriter の場合は、書き込み時にファイルに追加するのか、新規に書き込むのかを第二引数で指定できます。引数が一つの場合はファイルの先頭から新規書き込みとなり、既存のデータは失われます。詳細は API 仕様書を参照ください。
継承関係:
java.io.FileInputStream |
java.io.FileOutputStream |
|---|---|
java.lang.Object
|
+--java.io.InputStream
|
+--java.io.FileInputStream
|
java.lang.Object
|
+--java.io.OutputStream
|
+--java.io.FileOutputStream
|
コンストラクタ:
FileInputStream(File file) FileInputStream(FileDescriptor fdObj) FileInputStream(String name) FileOutputStream(File file) FileOutputStream(FileDescriptor fdObj) FileOutputStream(String name) FileOutputStream(String name, boolean append)
FileOutputStream の場合は、書き込み時にファイルに追加するのか、新規に書き込むのかを第二引数で指定できます。引数が一つの場合はファイルの先頭から新規書き込みとなり、既存のデータは失われます。詳細は API 仕様書を参照ください。
最初に文字ストリームを使ってみましょう。注意すべきことは、取り扱うファイルが存在しない場合は例外が発生すると言うことです。この例外はキャッチが必須です。
CCopy.java:
import java.io.*;
class CCopy {
public static void main(String[] args) {
try {
//ファイルオブジェクトの作成
File iFile = new File(args[0]);
File oFile = new File(args[1]);
//文字ストリームの作成
FileReader in = new FileReader(iFile);
FileWriter out = new FileWriter(oFile);
//読み込みと書き込み
int c;
while ((c = in.read()) != -1) {
out.write(c);
}
//ストリームを閉じる
in.close();
out.close();
System.out.println("コピー終了。");
} catch (IOException e) {
System.out.println("入出力例外が発生。");
System.out.println(e);
}
}
}
コマンドラインの第一引数から File オブジェクトをつくり、そこへ FileReader ストリームを作っています。同じく、第二の引数からも File オブジェクトを作って、 FileWriter ストリームを作っています。
c = in.read() は、オブジェクト in から一文字読み込み、 c に代入しています。ファイルが終了する (EOF: EndOfFile) など、読み込めなければ -1 が返ります。
out.write(c) は、オブジェクト out に、文字 c を出力しています。
読み込むファイルが存在しない場合は、例外 java.io.FileNotFoundException が発生します。他にも例外が発生する可能性のあるメソッドが使われているので、それらのスーパークラスである java.io.IOException 型でキャッチしています。更にそのスーパークラスである java.lang.Exception 型でキャッチしても良いでしょう。いずれにせよ、この型の例外はキャッチが必須です。更に上の制御へスローしても良いでしょう。
次の実行例は、クラスファイルと同じディレクトリに、 test.txt が存在していた場合のものです。コマンドライン引数に、読み込みファイルと書き込みファイルを指定します。
C:\IO>javac CCopy.java C:\IO>java CCopy test.txt test_c.txt コピー終了。 C:\IO>
実際にテキスト・ファイルがコピーされていることを確認してください。
画像/音声などのバイナリファイルの場合は、バイトストリーム FileInputStream/FileOutputStream を使います。上のサンプルのストリームの部分を次のように変更しましょう。
//バイトストリームの作成 FileInputStream in = new FileInputStream(iFile); FileOutputStream out = new FileOutputStream(oFile);
このクラスを BCopy.java として作成します。同じディレクトリに NEXTindex.gif が存在した場合の実行例を次に示します:
C:\IO>javac BCopy.java C:\IO>java BCopy NEXTindex.gif copy.gif コピー終了。 C:\IO>
文字ストリームのサンプル CCopy.java を少し修正して、コピーするだけではなく、各行ごとに行番号を追加して出力するように変えてみましょう:
Nl.java:
import java.io.*;
public class Nl {
public static void main(String[] args) throws IOException {
//ファイル名のインスタンス化
File inputFile = new File(args[0]);
File outputFile = new File(args[1]);
//入出力ストリームのインスタンス化
FileReader in = new FileReader(inputFile);
FileWriter out = new FileWriter(outputFile);
int c;
int i=1;
out.write(i+": ");
while ((c = in.read()) != -1) {
out.write(c);
if (c == '\n') {
i++;
out.write(i + ": ");
}
}
in.close();
out.close();
System.out.println("コピー終了。");
}
}
ここでは、例外をキャッチしないで、更に上の制御へスローしてしまっています。
\n は改行を表します。読み込んだ文字が改行文字ならば、その次に行番号を出力するように工夫しています。
C:\IO>javac Nl.java C:\IO>java Nl test.txt nltest.txt コピー終了 C:\IO>