JavaのBufferedInputStreamクラスとmarkメソッドを完全解説!初心者でもわかる読み取り位置の保存と復元
生徒
「Javaでファイルを読み込んでいるときに、一度読んだ場所に戻ることってできるんですか?」
先生
「できますよ!Javaにはmarkというメソッドがあって、読み取り位置を一時的に記録して、あとで戻ることができるんです。」
生徒
「それは便利そうですね。どうやって使うんですか?」
先生
「それでは、BufferedInputStreamとmarkメソッドについて、使い方や仕組みを一緒に学んでいきましょう!」
1. JavaのBufferedInputStreamクラスとは
BufferedInputStreamはJavaの標準ライブラリに含まれているInputStreamのサブクラスです。このクラスは、内部にバッファを持ち、ファイルなどからのデータ読み込みを高速化するために使われます。
たとえばファイルから1バイトずつ読み込む処理を、毎回ディスクから取得するのではなく、バッファに一時的にデータをまとめて読み込んでおくことで、読み取り回数を減らして高速化できるのです。
2. markメソッドとは?何ができるの?
markメソッドは、現在の読み取り位置を「記録(マーク)」しておくことができるメソッドです。その後、必要に応じてresetメソッドを呼ぶことで、記録しておいた位置に戻ることができます。
この機能は、同じ入力データを繰り返し処理したいときや、特定の条件によって読み取り位置を戻して再処理したい場合に便利です。たとえば、ファイルの先頭を読みながらデータの形式を判定し、その後必要に応じて最初から再読み込みするようなケースに使われます。
3. markメソッドの基本的な使い方
BufferedInputStreamでmarkメソッドを使うには、まずストリームがmarkSupportedメソッドでマーク機能に対応しているか確認することが重要です。BufferedInputStreamは対応しているので、安心して使えます。
次に、実際にmarkとresetを使ったサンプルコードを見てみましょう。
import java.io.BufferedInputStream;
import java.io.FileInputStream;
import java.io.IOException;
public class MarkExample {
public static void main(String[] args) {
try (BufferedInputStream bis = new BufferedInputStream(new FileInputStream("sample.txt"))) {
if (bis.markSupported()) {
bis.mark(100); // 読み取り位置をマーク(100バイトまで有効)
int first = bis.read();
int second = bis.read();
System.out.println((char) first);
System.out.println((char) second);
bis.reset(); // マークした位置に戻る
int again = bis.read();
System.out.println((char) again);
} else {
System.out.println("markはサポートされていません。");
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
A
B
A
この例では、最初に2バイト分のデータを読み込み、その後resetメソッドでマークした位置に戻り、もう一度読み直しています。「A」「B」「A」と表示されることで、markとresetの効果が確認できます。
4. markメソッドの引数の意味とは
markメソッドには引数として「readlimit(リードリミット)」を指定します。これは、markを設定してからresetを使うまでの間に、何バイトまで読み進められるかを指定する値です。
たとえば、mark(100)とすると、その後100バイト以内の読み込みであればresetで戻ることができますが、それ以上読み進めると戻れなくなる可能性があります。
5. markメソッドとresetメソッドを使うときの注意点
- 必ずmarkSupported()で確認する:すべての
InputStreamがmarkに対応しているわけではありません。BufferedInputStreamは対応しています。 - readlimitを超えるとresetできない:指定したバイト数以上を読み込んでしまうと、
resetで戻れなくなることがあります。 - バッファサイズとの関係:バッファサイズが小さい場合、
readlimitを超えるとマーク位置のデータが失われることがあります。 - resetはmarkを呼んだ後でしか使えない:
markを一度も呼ばずにresetを使うと、例外が発生します。
6. markメソッドはこんなときに便利
markメソッドは、入力ストリームの処理で次のようなケースに役立ちます。
- 一部のデータだけ読んで条件分岐をしたいとき
- 先頭の数バイトでファイル形式を判定してから再処理したいとき
- 解析処理で読み直しが必要なとき
たとえば、バイナリファイルのヘッダーを読んでファイル形式を判断した後、その位置に戻って全体を処理するような場面では、markとresetがとても役立ちます。
7. BufferedInputStreamとmarkメソッドを使いこなそう
BufferedInputStreamを使うことで、ファイルやデータの読み込みを効率的に行えるだけでなく、markメソッドによって柔軟なデータ処理も可能になります。
Javaのファイル処理では、ただ読み込むだけでなく、状況に応じて読み取り位置を制御することが求められます。markメソッドを使いこなせば、より高度なデータ処理にも対応できるようになります。
まとめ
BufferedInputStreamとmarkメソッドの理解を振り返ろう
この記事では、Javaの入出力処理の中でも特に重要なBufferedInputStreamクラスと、読み取り位置を一時的に保存できるmarkメソッドについて詳しく学びました。ファイルやデータを読み込む処理は、Javaプログラミングの基礎でありながら、実務や学習を進めるほど奥深さを感じる分野です。
BufferedInputStreamは、内部にバッファを持つことで、ディスクや外部データへのアクセス回数を減らし、読み込み処理を効率化する役割を担っています。単純にデータを読むだけでなく、処理速度やパフォーマンスを意識した設計になっている点が、Javaらしい特徴と言えるでしょう。
その中でもmarkメソッドは、現在の読み取り位置を一時的に記憶し、あとからresetメソッドでその位置に戻ることができる便利な仕組みです。これにより、データの先頭を確認してから処理を分岐したり、同じデータを何度か読み直したりすることが可能になります。
markとresetを使う際の重要なポイント
記事内でも触れたように、markメソッドを使う際にはいくつか注意点があります。まず、対象のストリームがmarkSupportedに対応しているかを確認することが重要です。BufferedInputStreamは標準で対応しているため、安心して利用できます。
また、markに指定するreadlimitの値は非常に重要です。この値を超えて読み進めてしまうと、resetで元の位置に戻れなくなる可能性があります。バッファサイズや読み込み量を意識しながら、適切な値を設定することが、安定したプログラムを書くためのポイントです。
まとめとしてのサンプルプログラム
ここで、これまで学んだ内容を振り返るために、BufferedInputStreamとmark、resetを組み合わせたシンプルなサンプルプログラムをもう一度確認してみましょう。記事内と同じクラス構成を使い、理解を深めることを目的としています。
import java.io.BufferedInputStream;
import java.io.FileInputStream;
import java.io.IOException;
public class MarkSummarySample {
public static void main(String[] args) {
try (BufferedInputStream bis =
new BufferedInputStream(new FileInputStream("sample.txt"))) {
if (bis.markSupported()) {
bis.mark(50);
int data1 = bis.read();
int data2 = bis.read();
System.out.println((char) data1);
System.out.println((char) data2);
bis.reset();
int dataAgain = bis.read();
System.out.println((char) dataAgain);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
このように、読み取り位置を一度保存しておくことで、処理の途中でも柔軟に読み直しができる点が、markメソッドの大きな魅力です。ファイル解析やデータチェックなど、さまざまな場面で応用できます。
生徒
「BufferedInputStreamって、ただ速く読むためだけのクラスだと思っていましたが、markメソッドと組み合わせると、読み取り位置まで管理できるんですね。」
先生
「その通りです。単なる高速化だけでなく、柔軟な読み取り制御ができるのが大きな特徴です。特にファイル形式の判定や解析処理ではよく使われますよ。」
生徒
「markとresetを使えば、一度読んだデータを無駄にせずに処理できるのが便利だと感じました。」
先生
「良い気づきですね。readlimitやバッファサイズを意識することで、より安全で効率的なJavaの入出力処理が書けるようになります。」
生徒
「これからは、ファイルを読むときにmarkメソッドが使えないか意識して考えてみます。」
先生
「それが大切です。基礎を理解していると、応用力も自然と身についていきますよ。」
以上が、BufferedInputStreamクラスとmarkメソッドについての総まとめです。Javaのファイル読み込み処理をより深く理解し、実践的に使いこなすための第一歩として、ぜひ繰り返し確認してみてください。