JavaのBufferedInputStreamクラスのresetメソッドを解説!マークした位置に戻る方法をわかりやすく紹介
生徒
「Javaでファイルを読み込んでいて、一度読んだ場所に戻ることってできますか?」
先生
「はい、BufferedInputStreamクラスのresetメソッドを使えば、事前にマークしておいた場所に戻ることができます。」
生徒
「えっ、マークってなんですか?どこかに目印みたいなのをつけるんですか?」
先生
「その通りです。まずmarkメソッドで読み取り位置を記録して、あとでresetでその場所に戻ることができます。今日はその使い方を詳しく説明しますね。」
1. BufferedInputStreamクラスとは
BufferedInputStreamクラスは、Javaでファイルやストリームのデータを効率よく読み取るためのクラスです。内部にバッファ(データの一時保存領域)を持っており、一度に多くのデータを読み込んでおくことで、読み取り速度を向上させることができます。
このバッファを活用することで、ディスクからの読み込み回数を減らし、全体のパフォーマンスが良くなるという特徴があります。
2. resetメソッドとは?
resetメソッドは、BufferedInputStreamでmarkメソッドを使って記録した読み取り位置に戻るためのメソッドです。
たとえば、あるデータを読み取ったあとで「やっぱりさっきの場所に戻りたい」というような場合に、このresetメソッドを使えばマークした位置まで戻ることができます。
3. resetメソッドの使い方
それでは、実際にBufferedInputStreamでmarkとresetを使って読み取り位置を戻す例を見てみましょう。
import java.io.BufferedInputStream;
import java.io.FileInputStream;
import java.io.IOException;
public class ResetExample {
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); // 再び最初の文字が出力される
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
A
B
A
このコードでは、最初に2バイト読み込んだあとでresetメソッドを使って先頭に戻り、再び最初のバイトを読み取っています。
4. resetメソッドを使うための条件
resetメソッドを使う前には、次の2つの条件を満たしている必要があります。
markメソッドを先に呼び出していることBufferedInputStreamがmarkSupportedでtrueを返すこと
これらを満たさずにresetを使おうとすると、IOExceptionが発生しますので注意しましょう。
5. readlimitとresetの関係
markメソッドにはreadlimitという引数があります。これは「マークした後、どれだけ読み進めても戻れるか」という最大バイト数の指定です。
このreadlimitを超えて読み進めてしまうと、resetで戻れなくなってしまうことがあります。そのため、markを使うときは、戻りたい位置からどれだけ読み取るかを考えて、適切なreadlimitを設定することが大切です。
6. resetメソッドを使うときの注意点
- markより前にresetを呼んではいけない:先にmarkしてからでないとresetは使えません。
- readlimitを超えるとresetできなくなる:BufferedInputStreamのバッファサイズに依存するため注意が必要です。
- resetを使うことで再解析ができる:ファイルの先頭数バイトで条件を判断し、戻って処理をやり直すような使い方が可能です。
7. resetメソッドの実用例
resetメソッドは以下のような場面で役立ちます。
- ファイルの先頭を少しだけ読んで形式を判断した後、先頭に戻って処理をやり直す
- データの一部を仮に読み取り、条件に応じて再度読み直す
- 一度処理したデータに戻って比較処理を行いたいとき
このように、resetメソッドはファイル解析やストリーム処理を柔軟にするために非常に便利な機能です。
8. BufferedInputStreamとresetメソッドでできること
JavaのBufferedInputStreamクラスとresetメソッドを組み合わせることで、一度読み取ったデータをもう一度利用することが可能になります。
マークとリセットはセットで活用する必要があり、特にファイル解析や複雑なデータ構造を扱う場面では大きな力を発揮します。初心者のうちからこの便利な仕組みを覚えておくと、後々のプログラミングに役立つ場面が増えていくでしょう。
9.まとめ
今回はJava言語で非常によく使われるBufferedInputStreamクラスのresetメソッドについて、初心者にもわかりやすいように丁寧に解説しました。ストリーム処理におけるmarkとresetの組み合わせは、ファイル解析やデータ再処理において非常に強力なテクニックです。読み取り位置を記憶して再びその位置に戻る機能は、たとえばファイルの先頭数バイトで判定処理を行ってから、最初から再読み込みしたい場面などで活用されます。
特に初心者がJavaのファイル処理を学ぶとき、BufferedInputStreamの内部バッファやreadlimitの存在に気付かずにつまずくことが多いです。今回紹介したように、markSupportedでresetの使用可否を事前に確認し、適切にmarkとresetを使い分けることで、安全かつ効率的なストリーム処理が可能になります。
また、readlimitの値によっては、resetが思うように動作しないこともあります。これは内部バッファのサイズに依存しており、必要以上に多くのデータを読み進めるとマーク位置が失われてしまいます。こうした挙動を理解しておくことで、IOExceptionなどの例外を未然に防ぎ、堅牢なプログラムを構築できます。
ここで改めて、基本的な使い方の復習として簡単なコード例をもう一度掲載しておきます。
import java.io.BufferedInputStream;
import java.io.FileInputStream;
import java.io.IOException;
public class ResetDemo {
public static void main(String[] args) {
try (BufferedInputStream bis = new BufferedInputStream(new FileInputStream("example.txt"))) {
if (bis.markSupported()) {
bis.mark(200);
int data1 = bis.read();
int data2 = bis.read();
System.out.println((char) data1);
System.out.println((char) data2);
bis.reset();
int data3 = bis.read();
System.out.println((char) data3);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
このように、BufferedInputStreamとresetメソッドを活用することで、柔軟なストリーム処理が可能になります。Javaのファイル操作において、読み取り位置の制御は極めて重要であり、今後XMLやCSVなどのデータ解析、あるいはネットワーク通信の際にも役立ちます。
Java初心者が今の段階でこのような便利なクラスやメソッドを知っておくことで、将来的により複雑な処理にもスムーズに対応できる力を身につけることができます。特にJavaのストリームAPIに慣れておくことは、オブジェクト指向プログラミングやデータ処理スキルを高めるうえで大きな財産となるでしょう。
生徒
先生、resetって思ったより便利ですね。ファイルを何度も開かなくても同じ場所に戻れるなんて!
先生
そうですね。markとresetを使えば、特定の位置に戻って何度も同じ処理ができます。データの先頭をチェックしてからやり直したいときには特に便利です。
生徒
でも、readlimitを超えると戻れないっていうのは少し怖いですね。そこは気をつけないと。
先生
そのとおりです。readlimitは、読み進めるバイト数の上限ですから、使い方を誤ると例外が発生します。慎重に設定しましょう。
生徒
これからはBufferedInputStreamを使うときは、markSupportedで確認するようにします!
先生
それが正解です。マークがサポートされているかどうかは必ずチェックしましょう。Javaの公式ドキュメントも読んで理解を深めてくださいね。