[java.io] Java文字列入力のまとめ (InputStream, Reader, Scanner)

最近、授業で Java を書くことになりました。
File, InputStream, FileReader, Scanner の関係がよくわからなかったのでまとめます。

この記事では、Java SE 1.8 を前提としています。
ただし、この記事は java.nio ではなく、古い java.io についてのまとめです。

コード中には、例外処理が書かれていませんが、ファイルを開くときには FileNotFoundException を、ファイルを読み書きするときには IOException を受け取れるようにしておく(または、さらに上のメソッドに投げる)必要があります。

ページの下の方にまとめの図があります。

java.io のリファレンス

https://docs.oracle.com/javase/jp/8/docs/api/java/io/package-summary.html

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();

利用の関係を表した図

java.io4.png

命名の法則

クラス名 分解 意味
FileInputStream File-InputStream File を InputStream に変換する。
InputStreamReader InputStream-Reader InputStream を Reader に変換する。
FileReader File-Reader File を Reader に変換する。