最近、授業で Java を書くことになりました。
File, InputStream, FileReader, Scanner の関係がよくわからなかったのでまとめます。
この記事では、Java SE 1.8 を前提としています。
ただし、この記事は java.nio ではなく、古い java.io についてのまとめです。
コード中には、例外処理が書かれていませんが、ファイルを開くときには FileNotFoundException を、ファイルを読み書きするときには IOException を受け取れるようにしておく(または、さらに上のメソッドに投げる)必要があります。
ページの下の方にまとめの図があります。
java.io のリファレンス
File, FileDescriptor
- java.io.File
パスの抽象表現(パスの単なる表現で開いたファイルを保持したりはしていない)
File file = new File("file.txt"); // ファイル名から作れる
- java.io.FileDescriptor: 開いたファイルを表す。ハンドルとして機能。
InputStream
バイトを読み込むためのクラス
- java.io.InputStream 抽象クラス
- java.io.FileInputStream: ファイルから InputStream を構築するためのクラス
- java.io.FilterInputStream: InputStream を保持するためのクラス
- java.io.BufferedInputStream: InputStream をバッファして自身も InputStream として見せる。
// System.in は InputStream のインスタンス
InputStream sytemin = System.in;
// ファイルからストリームを作る
InputStream fileStream = new FileInputStream("file.txt");
// ストリームをバッファする
InputStream bufferedStream = new BufferedInputStream(fileStream);
bufferedStream.close();
Reader
InputStream'Reader' のように名前の最後に 'Reader' とついているクラスは、文字列ストリームを読み込むためのクラスです。
- java.io.Reader 抽象クラス
- java.io.InputStreamReader: InputStream => Reader への橋渡し。文字セットを指定できる
- java.io.FileReader: 簡易クラス (File, FileDescriptor, fileName で Reader 構築。文字エンコーディングは指定できない。)
- java.io.BufferedReader: Reader クラスをバッファ
// ファイルからバイトストリームを作る
InputStream fileStream1 = new FileInputStream("file1.txt");
// バイトストリームから文字列ストリームを作る
Reader reader1 = new InputStreamReader(fileStream1);
// ファイルからバイトストリームを作る
InputStream fileStream2 = new FileInputStream("file2.txt");
// 文字列ストリームを作る。文字列エンコードの指定
Reader reader2 = new InputStreamReader(fileStream2, "utf-8");
// 簡易クラスを使って、ファイルから Reader を直接作る
Reader reader3 = new FileReader("file3.txt");
// リーダーをバッファする
BufferedReader bufferedReader3 = new BufferedReader(reader3);
// BufferedReader には、テキスト行を読み込む readLine() がある
String line = bufferedReader3.readLine();
reader1.close();
reader2.close();
bufferedReader3.close();
java.util.Scanner
テキストから int, long, boolean などのプリミティブ型や文字列を取得するスキャナー。
File クラスや、InputStream クラスから構築できる。文字列エンコーディングも指定できる。
区切り文字のマッチングを正則表現で指定できる。
詳しくは、https://docs.oracle.com/javase/jp/8/docs/api/java/util/Scanner.html
// System.in から数値を読み込み
Scanner sc1 = new Scanner(System.in);
int i = sc1.nextInt();
// File から構築
Scanner sc2 = new Scanner(new File("file.txt"));
// Scanner sc2 = new Scanner("file.txt")); とはできない。
// このようにした場合、"file.txt" という文字列を読もうとしてしまう。
// 区切りをコンマに変更
sc2.useDelimiter(",");
// 区切りごとに1行ずつ表示
while (sc2.hasNext())
{
String str = sc2.next();
System.out.println(str);
}
// sc1.close();
sc2.close();
利用の関係を表した図
命名の法則
クラス名 | 分解 | 意味 |
---|---|---|
FileInputStream | File-InputStream | File を InputStream に変換する。 |
InputStreamReader | InputStream-Reader | InputStream を Reader に変換する。 |
FileReader | File-Reader | File を Reader に変換する。 |