0

私が実装しているAPIは、階層構造のデータ、つまりネストされたブロックを含むInputStreamsを処理します。これには、リーフブロック内の多数の画像が含まれます。(知っておく必要がある場合は、私が解析しているのはCBEFFデータです。)データの各ブロックには、そのブロックに関するメタデータを含むヘッダーがプレフィックスとして付けられます。

1st level 1 header
    1st level 2 header
    1st level 2 data block
    2nd level 2 header
    2nd level 2 data block
2nd level 1 header
    3rd level 2 header
    3rd level 2 data block

元のInputStreamは、私のAPIクラスのコンストラクターへの引数であり、階層の下に渡されます。現在、APIクラスのコンストラクターで画像をバイト配列に読み込んでいるため、各コンストラクターは、そのクラスが担当する完全なデータを読み取りながらブロックし、後でクライアントがそのAPIクラスの関連するgetterメソッドを呼び出すと取得します。メモリから提供される画像データ。含まれている画像を何らかの怠惰なInputStreamの形式でAPIのクライアントに提供したいので、クライアントが結果のInputStreamのバイトを読み取った結果として元のInputStreamからのみ画像バイトが読み取られます。ゲッター。これにより、たとえば、プログレッシブレンダリングを実行できます。これは、元のInputStreamが遅いため便利です。

InputStreamsでこれを解決するエレガントな方法はありますか?

4

1 に答える 1

1

InputStreamランダムアクセスには適していません。したがって、との組み合わせを使用して一部の入力ストリームで同様の効果を達成できる場合でも、その一部を読み取ることはほとんどの場合機能しません。ただし、すべてのストリームがをサポートしているわけではなく、バイトのスキップはバイトの読み取りと同じくらいコストがかかることがよくあります。resetskipreset

したがって、別のアプローチを試すことをお勧めします。ストリーム全体を一時ファイルなどのランダムアクセスバッファにバッファリングします。これは、そもそもストリームからすべてのバイトを読み取ることを意味します。または、元のソースにランダムアクセスする方法を見つけます。処理しているソースの種類を指定していませんが、たとえばHTTP接続の場合、範囲要求を使用してパーツをダウンロードできます。同様のソリューションが他のソースでも機能する可能性があります。

ランダムアクセスをどのように実装するかに関係なく(そしてコメントを見ると、InputStreamwithresetとを使用して実装する可能性がありskipます)、そのストリームの一部を表す独自のクラスを作成できます。InputStreamサブクラス化することで、そのクラス自体をのインスタンスにすることができますFilterInputStream

cLass SubStream extends FilterInputStream {
    private long offset;
    public SubStream(long offset, InputStream parent) {
        super(parent);
        this.offset = offset;
    }
    public SubStream(InputStream parent) {
        this(0, parent);
    }
    @Override public void reset() throws IOException {
        in.reset();
        in.skip(offset);
    }
    public SubStream subStream(long offset) {
        return new FilterInputStream(this.offset + offset, in);
    }
    public Object syncObject() {
        return in;
    }
}

これらのストリームのいずれかを使用する操作がreset最初に呼び出されることを確認する必要があります。適切なエンドオブストリーム処理を実施する必要がある場合は、ほとんどのread実装をオーバーライドする必要があります。同時アクセスが可能な場合は、基になるストリームの操作を同期する必要があります。したがって、このクラスを使用するコードは次のようになります。

     synchronized(part.syncObject()) {
         part.reset();
         return read(part);
     }
于 2012-08-13T09:17:44.173 に答える