InputStream/OutputStream型
OutputStream 型
データを書き出すための Stream であり,使い方は Writer
とほぼ同じです.
例えば,以下のサンプルプログラムの writeWithWriter
は
Writer 型で示した典型的なWriter
の使い方です.
このwriteWithWriter
と対比して,writeWithOutputStream
を確認してください.
void writeWithWriter(File file, String message) throws IOException{
PrintWriter out = new PrintWriter(new FileWriter(file)); // (2)
// 上記の(2)の処理を区別して書くと次のような処理になる.
// FileWriter fwriter = new FileWriter(file);
// PrintWriter out = new PrintWriter(fwriter);
out.print(message);
out.close();
}
void writeWithOutputStream(File file, String message) throws IOException{
BufferedOutputStream out = new BufferedOutputStream(new FileOutputStream(file)); // (3)
// 上記の(3)の処理を区別して書くと次のような処理になる.
// FileOutputStream fout = new FileOutputStream(file);
// BufferedOutputStream out = new BufferedOutputStream(fout);
out.write(message.getBytes());
out.close();
}
writeWithWriter
とwriteWithOutputStream
の違いは,メソッド内で利用している型のみで,構造がほぼ同じであることに注意してください.
writeWithOutputStream
では,ファイルを開き,その型(ここではFileOutputStream
)を別の型(BufferedOutputStream
)でラップしています.
そして,BufferedOutputStream
で message.getBytes()
の返り値をwrite
メソッドで書き出しています.
message.getBytes()
は名前から想像できるように,文字列(String
型)のバイト配列を返します.
このことから,OutputStream
は文字データ(Character
型)ではなく,バイナリデータ(Byte
型)を扱うことに注意しましょう.
加えて,利用している型は異なりますが,名前が似ている型があることにも注意しましょう.
例えば,writeWithWriter
メソッドでは,中で FileWriter
を利用していますが,
writeWithOutputStream
メソッドでは,FileWriter
ではなく,FileOutputStream
を利用しています.
OutputStream 型色々
OutputStream
型もWriter
型と同様に多くの型が存在します.
ファイルに書き出すときは,FileOutputStream
を使いますが,典型的には
OutputStream
の機能のみ(write
メソッドにInetger
型を渡す)を使うことが多いでしょう.
FileOutputStream
- ファイル(
File
型)にデータを書き込むためのOutputStream
型.
- ファイル(
ByteArrayOutputStream
- メモリ上にデータを書き出し,バイト配列で取得できる
OutputStream
型.
- メモリ上にデータを書き出し,バイト配列で取得できる
GZIPOutputStream
- この
OutputStream
にデータを書き出すと zip 圧縮されるようになる.
- この
InputStream 型
InputStream
はデータを読み込むための Stream であり,バイナリデータを読み込みます.
使い方は Reader
とほぼ同じで,Stream を開き,そこからデータを読み取ります.
read
メソッドで1バイトのデータを読み込みます.この時,Integer
型でデータが返されます.
返り値となるデータが-1 の場合,これ以上,読み取るデータがないことを表します.
InputStream 型色々
InputStream
型もReader
型と同様に多くの型が存在します.
ファイルからデータを読み出すときは,FileInputStream
を使います.
また,読み込むときにバッファリングしたい場合は,BufferedInputStream
を使うことが多いでしょう.
それでも,本講義で扱うプログラムでは,引数のないread
メソッドを呼び出し,1 バイト単位で読み込む方法で十分でしょう.
FileInputStream
- ファイル(
File
型)からバイナリデータを読み込むためのInputStream
型.
- ファイル(
BufferedInputStream
- データをバッファリングして読み込むための
InputStream
型.
- データをバッファリングして読み込むための
ByteArrayInputStream
- バイト配列から1バイトずつデータを読み込むための
InputStream
型.
- バイト配列から1バイトずつデータを読み込むための
GZIPInputStream
- gzip 圧縮されたファイルを
FileInputStream
で開き,このGZIPInputStream
でラップして読み込むと,gzip 圧縮された内容を読み込むことが可能です.
- gzip 圧縮されたファイルを
例題 4 InputStream を利用した Cat
InputStream
はバイナリデータですので,行の概念がありません.改行コードも文字も同列に扱われるためです.
それでも,例題 1のようなプログラムを作成可能です.
1バイトずつ読みこみ,1バイトずつ書き出せば良いのです.
以下の例をコンパイル,実行してください.
import java.io.*;
public class CatByStream{
void cat(String file) throws IOException{
System.out.printf("========== %s ==========%n", file);
FileInputStream in = new FileInputStream(file);
this.printFileContent(in);
in.close();
}
void printFileContent(FileInputStream in) throws IOException{
Integer data;
while((data = in.read()) != -1){
System.out.write(data);
}
}
// run や main メソッドは省略.
}
このプログラムのprintFileContent
メソッドを見てみましょう.
FileInputStream
型の変数in
に対してread
メソッドを呼び出し,1バイトのデータを受け取っています.
読み取れるデータがない場合は -1
が返されます.
そして,受け取ったデータを変数data
に代入し,System.out.write
メソッドが標準出力に書き出しています.
このように1バイト単位で読み出し,書き出しすることでも,Cat コマンドを実現可能です.
例題 5 単純なファイルコピー 2
それでは,例題 3 単純なファイルコピーを InputStream
/OutputStream
を使って書き直して見ましょう.
クラス名は SimpleCopier2
としてください.
例題 6 pnm 画像の生成
pnm 画像とは,pbm, pgm, ppm の総称で非常に単純な画像フォーマットです. それぞれ,portable binary map, portable gray map, portable pix map の略です. ここで,ppm 画像を作成します. ppm画像は 3 バイトで1画像を表します.画素とは画像の1ピクセルのことです. 1画素は R(赤成分),G(緑成分),B(青成分)の3つの成分で構成されます.
ppm 画像は,次のようなフォーマットです.各行は1バイトの改行(\n
)で区切られます.
このうち,WIDTH
は横幅を表す整数値,HEIGHT
は高さを表す整数値で,画像データはバイナリデータで画素の左上から始まり左に向かって出力されます.
一番右端のデータが書かれれば,一段下の行の左端からのデータが書き出されます.
そして,1画素あたり,R(赤成分),G(緑成分),B(青成分)の順で書き出され,これがWIDTH*HEIGHT
だけ続きます.
P6
WIDTH HEIGHT
255
画像データ
このような ppm 画像で,下に示すようなグラデーション表示をしてみましょう. 256×256 の大きさで,左上が黒(RGB がそれぞれ 0),左下が赤,右上が青,右下がマゼンタ(RGB で R と B 成分が 255,G 成分が 0)になるように画像を作成してみましょう. なお,ppm 画像は,macOS のプレビューで確認できます.
では,GradiationGenerator
というクラス名で作成してみましょう.
生成した画像を gradiation.ppm
というファイルに出力しましょう.

生成するグラデーション画像
// import文は省略
public class GradiationGenerator {
void run() throws IOException{
OutputStream out = // gradiation.ppm に出力する OutputStream を構築する.
this.writeHeader(out);
this.writeBody(out);
out.close();
}
void writeBody(OutputStream out) throws IOException{
// 各画素をR, G, B それぞれ1バイトで出力する.
}
void writeHeader(OutputStream out) throws IOException{
out.write('P'); // ヘッダ部分は文字で表される.
out.write('6');
out.write('\n'); // 環境が変わっても \n を出力する必要がある.
out.write('2'); // 横幅
out.write('5');
out.write('6');
out.write(' ');
out.write('2'); // 高さ
out.write('5');
out.write('6');
out.write('\n');
out.write('2'); // 1画素の1色成分の最大値
out.write('5');
out.write('5');
out.write('\n');
}
// mainメソッドは省略.
}