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

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

続・Java でストリーム

昨日の話の続き。
結局、BufferedInputStream で mark()/reset() を使わずにやるようにした。
HTTPヘッダは、バッファを用意して改行が連続するところまで読み込む。その後に続く Content-length 分のデータが、Content-Type で指定されたデータと見なすようにした。

    private String getHeaders(BufferedInputStream in) throws IOException {
        byte buff = new byte[8192];
        int pos = 0;
        while (true) {
            buff[pos] = read(in);
            if (pos > 0) {
                if (buff[pos - 1] == '\r' && buff[pos] == '\r') {
                    break;
                }
            }
            if (pos > 2) {
                if (buff[pos - 3] == '\r' &&
                    buff[pos - 2] == '\n' &&
                    buff[pos - 1] == '\r' &&
                    buff[pos] == '\n') {
                    break;
                }
            }
            pos++;
        }
        ByteArrayInputStream bis = new ByteArrayInputStream(buff);
        BufferedReader reader = new BufferedReader(new InputStreamReader(bis));
        ArrayList list = new ArrayList();
        while (true) {
            String s = reader.readLine();
            if (s == null || s.length() == 0) {
                break;
            }
            list.add(s);
        }
        String s = new String[list.size()];
        s = (String)list.toArray(s);
        return s;
    }

上のコードの最初の方にある read() は、以下のとおり。

    private byte read(InputStream in) throws IOException {
        int b = -1;
        while (true) {
            b = in.read();
            if (b >= 0) {
                break;
            }
            try {
                Thread.sleep(1);
            } catch (InterruptedException e) {}
        }
        return (byte)b;
    }

この read() は重要。1バイトのデータを読むためにループしている点に注意して欲しい。ネットワークを通して届くデータは、ストリームから read() した時点ではまだ届いていない可能性がある。ノンブロッキングモードでは、データが読めるまで read() を繰り返し呼び出さないといけない。(ネットワークプログラミングの初心者は、このことに気付かずに、データがきちんと受信できない原因について悩みつづけることが多い。)
エラーハンドリングは、呼び出し側で行う。データの終端まで読み終えたときに read() すると EOFException が発生するし、ソケットがクローズされた場合は IOException が発生するので、それらを適切に処理すればよい。