JavaのBufferedInputStreamクラスとmarkSupportedメソッドを解説!マーク機能が使えるか確認する方法
生徒
「Javaでストリームの読み取り位置を戻せるって聞いたんですが、全部のクラスでできるんですか?」
先生
「全部ではありません。markやresetが使えるかは、クラスによって違うんです。その確認に使うのがmarkSupportedメソッドです。」
生徒
「なるほど、使えるかどうかを調べる方法があるんですね。それって実際にはどうやって使うんですか?」
先生
「それでは、BufferedInputStreamとmarkSupportedメソッドの使い方を詳しく見ていきましょう。」
1. BufferedInputStreamクラスとは
BufferedInputStreamは、Javaでデータをバッファに一時的にためながら読み取るためのクラスです。バッファ機能があることで、読み取り操作の効率が向上し、パフォーマンスの高い入出力が可能になります。
ファイルやネットワークなどからデータを1バイトずつ読み込むよりも、BufferedInputStreamを使えばまとめてデータを読み込んでくれるので、処理が速くなります。特に大きなファイルを読み取るときに便利です。
2. markとresetは便利な機能
BufferedInputStreamでは、ストリームの現在位置を記録しておき、後からその位置に戻ることができます。それを実現するのがmarkとresetメソッドです。
たとえば、ファイルの先頭から少し読み取ってみて、必要があれば最初から再読み込みしたいといったケースで役立ちます。ただし、すべてのストリームでmarkやresetが使えるわけではありません。そこで登場するのがmarkSupportedメソッドです。
3. markSupportedメソッドとは?
markSupportedメソッドは、現在使っているInputStreamがmarkとresetに対応しているかどうかを確認するためのメソッドです。戻り値はboolean型で、対応していればtrue、非対応ならfalseが返ります。
たとえば、FileInputStream単体ではmarkに対応していませんが、それをBufferedInputStreamでラップすれば、mark機能が使えるようになります。
4. markSupportedメソッドの使い方を見てみよう
import java.io.BufferedInputStream;
import java.io.FileInputStream;
import java.io.IOException;
public class MarkSupportedExample {
public static void main(String[] args) {
try (BufferedInputStream bis = new BufferedInputStream(new FileInputStream("sample.txt"))) {
if (bis.markSupported()) {
System.out.println("このストリームはmarkに対応しています。");
} else {
System.out.println("このストリームはmarkに対応していません。");
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
このストリームはmarkに対応しています。
このように、BufferedInputStreamではmarkSupportedメソッドがtrueを返すため、安心してmarkやresetを使うことができます。
5. markSupportedがfalseの場合はどうする?
もし、使っているストリームでmarkSupportedメソッドがfalseを返した場合は、そのままではmarkやresetは使えません。
その場合は、BufferedInputStreamやPushbackInputStreamなど、mark対応のクラスでラップすることで対応できます。たとえば以下のように使います。
import java.io.BufferedInputStream;
import java.io.FileInputStream;
import java.io.InputStream;
public class WrapExample {
public static void main(String[] args) throws Exception {
InputStream original = new FileInputStream("sample.txt");
InputStream wrapped = new BufferedInputStream(original);
System.out.println("mark対応: " + wrapped.markSupported());
}
}
mark対応: true
BufferedInputStreamで包むことで、もともと対応していなかったFileInputStreamも、mark機能が使えるようになります。
6. markSupportedとバッファサイズの関係
markSupportedメソッドがtrueを返しても、markやresetが常に成功するとは限りません。内部バッファのサイズが小さいと、読み込みが進むにつれてマーク位置のデータが失われる可能性があります。
そのため、markを使うときは、必要な分の読み取りバイト数(readlimit)をしっかり指定し、必要に応じてバッファサイズを大きくすることも検討しましょう。
7. markSupportedの使いどころと実用例
Javaでストリーム処理を行う際には、入力の途中で条件分岐したり、データを戻して再解析する場面があります。そのような場合にmarkSupportedを使って事前に確認しておけば、安全にmarkとresetが使えます。
特に以下のようなシーンで役立ちます。
- ファイルの先頭を読み取って形式判定後に戻す処理
- データ解析中に複数の解釈候補を試したいとき
- ネットワーク経由で受信したバイナリデータのヘッダー解析
このような実用例でも、markSupportedを先に呼び出すことで、対応可否を事前に把握し、処理の安全性と信頼性を高めることができます。