ファイルの入出力

ファイルの入出力

ストリーム(Stream)

Javaで入出力を扱うには,ストリームという概念の理解が必要です. ストリームとは,データを流れとして扱う仕組みです. データがデータソース(Data Source; データの源,入力元)から流れてくる入力ストリームと, データをデータの出力先(Data Destination; 出力先)に流し込む出力ストリームの2つがあります.

下の画像が入力ストリームを表しています. データソースはファイルやネットワークから,もしくは,別のプログラムであるなど, 入力ストリームを扱う側は知らなくても良いようになっています. とにかく,ストリームを扱う側は,必要なデータが流れてくることさえ理解していれば良いわけです. このような性質のため,Javaでは,あらゆる入出力にストリームを利用します.

プログラムへの情報の読取り

入力元がファイルであろうと,ネットワークの先であろうと,受け取る方法は同じです. 入力元がどこであろうと,同じように扱うために,ラッピング という作業が必要になります.

下の画像が出力ストリームを表しています.出力も入力ストリームと同じく, ラッピングを利用して,出力先を気にすることなくデータを書き込めます.

プログラムからの情報の書き込み

ファイル,ネットワーク,また,メモリに書き込むときにもストリームを利用します.

ラッピング(Wrapping)

先ほど,ファイルやネットワーク,さては,メモリの入出力までストリームを利用できると述べました. 異なるものを同じように扱うために,ラッピング(wrapping)と言う概念を利用します. ラッピングは,アダプタパターン(Adapter Pattern)と言われる場合もあります.

ラッピングとは,包むや包装するという意味です. その意味のとおり,ラッピングを行うには,とある実体を別の型で覆います. 右図のように,別の型で覆うことで,内側の型(Inner)を外側の型(Outer)として扱えるようになります.

// Inner.java
public class Inner{
  void method1(){
    // some operation...
  }
}
// Outer.java
public class Outer{
  Inner inner
  void method2(){
    inner.method1();
  }
}
// Main.java
public class Main{
  void run(){
    Inner inner = new Inner();
    Outer outer = this.wrap(inner);
    outer.method2();
  }
  Outer wrap(Inner inner){
    Outer outer = new Outer();
    outer.inner = inner;
    return outer;
  }
}

Reader/Writer, InputStream/OutputStream

Javaのストリームを扱う型は下の図のように,ReaderWriterInputStreamOutputStreamの4種類に大別できます.

上図を縦のグループで見ると,Reader/Writerがテキストデータを 扱う型,InputStream/OutputStreamがバイナリデータを扱う型です. バイナリデータとは,画像ファイルや音声ファイルなどです. 文字を扱う型では,HTMLやプログラムのソースファイルなど,テキストデータを扱います.

一方,上図を横のグループで見ると,ReaderInputStreamが入力ストリームを 表しており,WriterOutputStreamが出力ストリームを表しています. そして,Readerと呼ばれる型にも複数の型が存在します.Writerも同じく, 複数のWriter型が存在します.

import文

4種類のストリームを扱う場合は,import文が必要です. それぞれの型の先頭にjava.io.をつけたものを import してください. 例えば,ReaderWriterを使いたい場合は,次の2行がプログラムの先頭に必要です.

import java.io.Reader;
import java.io.Writer;

Reader型の例えば,FileReaderBufferedReader を利用するときには,次の2行が必要です.

import java.io.BufferedReader;
import java.io.FileReader;

複数の import 文をまとめるために,import java.io.*;としても構いません. 先ほどのReaderWriterのimportの2行を1行で書けるようになります.