/** * * Copyright (C) 2006-2007 佐藤 雅俊/しいしせねっと * */ package net.siisise.io; import java.io.*; /** * ビット単位の入出力をする。 * 要テスト * @version 0.3 * @auther 佐藤 雅俊 */ public class BitInputStream extends FilterInputStream { /** 読み残しビット数 */ int topbit; /** 読み残しビット */ int buff; public BitInputStream(InputStream in) { super(in); topbit = 0; buff = 0; } /** * ビット処理をリセットしてしまいます * 読み込んでいない8ビット未満のビットデータは破棄されます。 */ @Override public int read() throws IOException { topbit = 0; buff = 0; return super.read(); } /** * ビット処理を考慮せずデータを読み込みます。 * 読み込んでいない8ビット未満のビットデータは破棄されます。 * * 2007-12-03 忘れていたらしいので追加 * * @param data データを受け取る配列 * @param off オフセット(バイト単位) * @param length 受け取る長さ(バイト単位) * @return */ @Override public int read( byte[] data, int off, int length ) throws IOException { topbit = 0; buff = 0; return super.read(data, off, length); } /** * ビット単位で読む * 0〜32ビットに対応 * EOF 未対応 */ public int readBit(int len) throws IOException { int r = 0; while (topbit < len) { r <<= topbit; r |= buff; len -= topbit; topbit = 0; buff = in.read(); if (buff == -1) { // 未対応 throw new java.io.EOFException("未実装なので"); } topbit += 8; } topbit -= len; r <<= len; r |= buff >>> topbit; buff &= (1 << topbit) - 1; return r; } /** * 指定ビットを配列に格納する * offset,bitlen はビット単位 * とりあえず 0で考える * dtの格納前のデータは破壊されるので要修正? */ public int readBit(byte[] dt, int offset, int bitlen) throws IOException { int retlen; int readOffset = offset / 8; offset = offset % 8; if (offset == 0 && topbit == 0 && bitlen >= 8) { // offset が 0の場合最適化 retlen = in.read(dt, readOffset, bitlen / 8) * 8; if (retlen < 0) { return -1; // throw new java.io.EOFException("どうする"); } readOffset += retlen / 8; bitlen -= retlen; } else { // 通常処理だったり retlen = 8 - offset; if (bitlen >= retlen) { // 要ビットマスク dt[readOffset++] = (byte) readBit(retlen); bitlen -= retlen; offset = 0; } } // 1バイトずつ読んでみる処理 while (bitlen >= 8) { dt[readOffset++] = (byte) readBit(8); bitlen -= 8; retlen += 8; } // 残りビットの読み取りとシフト if (bitlen > 0) { dt[readOffset] = (byte) readBit(bitlen); dt[readOffset] <<= 8 - bitlen - offset; retlen += bitlen; } return retlen; } public int readBit(byte[] data) throws IOException { return readBit(data, 0, data.length * 8); } /** * バイト単位でデータのある位置のうしろまでシーク * 未完成 */ public void find(byte[] pattern) throws IOException { int read; int offset = 0; while (offset < pattern.length) { do { // 先頭バイト検索 read = in.read(); } while ((byte) read != pattern[0]); read = in.read(); if ((byte) read == pattern[offset]) { offset++; } } } }