今日の役に立たない一言 - Today’s Trifle! -

古い記事ではさまざまなテーマを書いていますが、2007年以降はプログラミング関連の話がほとんどです。

java.io.BufferedInputStream の挙動

C++ だとか MIBファイルを書くための英文を書くとか、違う仕事が多かったが、今日は久しぶりに仕事で Java のコードを書いた。
Jar ファイルに埋め込んだテキストファイルの内容を読むコードを書いていた。

    public void readResource() throws IOException {
        InputStream in = getClass().getResourceAsStream(RESOURCE_NAME);
        BufferedReader br = new BufferedReader(new InputStreamReader(in));
        br.mark(256);
        String line = br.readLine();
            :
        br.reset();
            :
    }

すると、mark() して reset() すると、IOException が発生する!

java.io.IOException: Resetting to invalid mark
        at java.io.BufferedInputStream.reset(BufferedInputStream.java:368)
            :

BufferedReader#markSupported() をチェックしてみるが、true が返されている。
なぜ reset() できないんだろう???
原因が分からないまま、次のようにコードを変更してみるとうまくいくようになった。

    public void readResource() throws IOException {
        InputStream in = getClass().getResourceAsStream(RESOURCE_NAME);
        ByteArrayInputStream bis = toByteArrayInputStream(is);
        BufferedReader br = new BufferedReader(new InputStreamReader(in));
        br.mark(256);
        String line = br.readLine();
            :
        br.reset();
            :
    }

    private ByteArrayInputStream toByteArrayInputStream(BufferedInputStream bis) throws IOException {
        StringBuffer sb = new StringBuffer();
        BufferedReader br = new BufferedReader(new InputStreamReader(bis));
        while(br.ready()){
            sb.append(br.readLine());
            sb.append("\n");
        }
        byte b[] = sb.toString().getBytes();
        return new ByteArrayInputStream(b);
    }

読み込んでいるファイルのサイズは1KBもない小さなものだ。それに、mark()している場所までのサイズはたったの256バイト。BufferedReader のデフォルトバッファサイズは8KBなので、ファイル全体を読み込むにも十分なのに。
納得がいかない。(けど、動いたからいいか。)