1.

Java InputStreamの使い方|read・FileInputStreamとtry-with-resources

編集
この記事の要点
  • InputStream は Java のバイト入力ストリームを表す抽象クラス(java.io.InputStream
  • read() で 1 バイトずつ、read(byte[]) でまとめて読み込む。EOF は -1 を返す
  • 実装クラスは FileInputStream / ByteArrayInputStream / FilterInputStream(バッファ・圧縮等)など
  • 小さな read() を多用するなら BufferedInputStream で包んで I/O 回数を削減する
  • バイト列を文字列として扱うなら InputStreamReader + 文字コード指定 (StandardCharsets.UTF_8) でブリッジする
  • 必ず try-with-resources で囲み、自動 close() でリソースリークを防ぐ

InputStream とは

InputStreamjava.io パッケージに含まれる抽象クラスで、バイト単位の入力ストリームを表します。ファイル・ネットワーク・メモリ上のバイト列・標準入力(System.in)など、入力の供給元を抽象化した共通のインタフェースであり、Java の I/O はこのクラスを起点に組み立てます。

「テキスト(文字)」ではなく「バイト」を扱う点が 文字列API 側の Reader と対になります。CSV や JSON のような文字データを読みたい場合は InputStreamReader でラップして文字コードを与えるのが正しい使い方です。

主要メソッド

シグネチャ戻り値説明
int read()0–255 / -11 バイト読み込む。EOF で -1
int read(byte[] b)読み込んだバイト数 / -1配列にまとめて読む
int read(byte[] b, int off, int len)読み込んだバイト数 / -1オフセット指定で読む
byte[] readAllBytes()byte[]残りすべてを一括読み込み(Java 9+)
long skip(long n)実際にスキップしたバイト数n バイト読み飛ばす
int available()残りの推定バイト数ブロックせずに読み出せるバイト数の目安(保証ではない)
void close()ストリームを閉じる。try-with-resources が自動で呼ぶ

FileInputStream でファイルを読む

もっとも基本的な実装クラスは FileInputStream です。ファイルを 1 バイトずつ読む例。

import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;

public class Sample {
    public static void main(String[] args) throws IOException {
        try (InputStream in = new FileInputStream("input.bin")) {
            int b;
            while ((b = in.read()) != -1) {
                System.out.printf("%02X ", b);
            }
        }
    }
}

read()int を返しますが、有効値は 0–255 です。-1EOF(ストリーム末尾)を意味します。

バッファ付きで高速化:BufferedInputStream

1 バイトずつの read() はシステムコールが多発して遅くなります。BufferedInputStream でラップすると内部バッファ(既定 8KB)にまとめて読み込むため、I/O 回数が激減します。

import java.io.BufferedInputStream;
import java.io.FileInputStream;
import java.io.InputStream;

try (InputStream in = new BufferedInputStream(new FileInputStream("big.bin"))) {
    byte[] buf = new byte[4096];
    int n;
    while ((n = in.read(buf)) != -1) {
        // buf[0..n) を処理
    }
}

文字列として読みたいときは InputStreamReader

バイトを文字にするには、文字コードを明示して InputStreamReader でブリッジします。BufferedReader と組み合わせると 1 行ずつ読めます。

import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;

try (InputStream in = new FileInputStream("data.txt");
     BufferedReader br = new BufferedReader(
         new InputStreamReader(in, StandardCharsets.UTF_8))) {
    String line;
    while ((line = br.readLine()) != null) {
        System.out.println(line);
    }
}

文字コードを省略するとプラットフォーム既定(Windows なら Shift_JIS など)になり文字化けの温床になるので、必ず StandardCharsets.UTF_8 を渡してください。

主な実装クラス

クラス供給源用途
FileInputStreamファイルローカルファイルからバイトを読む
ByteArrayInputStreambyte[]メモリ上のバイト配列を InputStream として扱う
BufferedInputStream他の InputStreamバッファリングして高速化
DataInputStream他の InputStreamプリミティブ型(int / long / UTF-8 文字列)を読む
ObjectInputStream他の InputStreamシリアライズされたオブジェクトを復元
GZIPInputStream他の InputStreamGZIP 圧縮されたデータを展開しながら読む
System.in標準入力コンソールからの入力

NIO の Files.newInputStream との使い分け

Java 7 以降は Files.newInputStream(Path) も使えます。FileInputStream よりも例外メッセージが分かりやすく、ストリームAPI と相性が良いため、新規コードはこちらが推奨です。

import java.io.InputStream;
import java.nio.file.Files;
import java.nio.file.Path;

try (InputStream in = Files.newInputStream(Path.of("data.bin"))) {
    byte[] all = in.readAllBytes(); // Java 9+
    System.out.println("read = " + all.length + " bytes");
}

よくあるミスと対処

症状原因 / 対処
FileNotFoundExceptionパス間違い / カレントディレクトリ違い。Path.toAbsolutePath() でログ出力して確認
大量の read() で激遅BufferedInputStream でラップする / read(byte[]) でまとめ読みする
文字化けバイトを直接 String 化していないか確認。InputStreamReaderUTF_8 を渡す
available() の値で配列を確保したのに尻切れavailable() はあくまで「ブロックせず読める数の目安」。残量取得用ではない。readAllBytes()ByteArrayOutputStream へ詰め直す
close() 忘れでファイル数上限エラー必ず try-with-resources を使う

関連

編集
Post Share
子ページ

子ページはありません

同階層のページ
  1. InputStream
  2. OutputStream

最近更新/作成されたページ