13

バイナリ ストリームを処理していて、興味のない範囲のデータを効率的にスキップして、処理されるデータにスキップする必要があります。

InputStream.skip(long)保証の点ではあまり効果がありません:

この入力ストリームから n バイトのデータをスキップして破棄します。skip メソッドは、さまざまな理由で、より少ない数のバイト (場合によっては 0) をスキップすることがあります。これは、いくつかの条件のいずれかが原因である可能性があります。n バイトがスキップされる前にファイルの終わりに到達することは、1 つの可能性にすぎません。スキップされた実際のバイト数が返されます。

次の 2 つのいずれかが発生したことを確認する必要があります。

  1. ストリームは終了しました
  2. バイトがスキップされました

十分に単純です。ただし、この説明で許容される寛大さは、たとえば、BufferedInputStream数バイトをスキップして戻ることができることを意味します。確かに、それらのいくつかだけがスキップされたことがわかりますが、その理由は明らかではありません.

私の質問は次のとおりです。InputStream.skip(long)ストリームが終了するか、スキップが正常に完了するかを知るような方法で利用できますか?

4

3 に答える 3

12

メソッドコントラクトはかなり奇妙なので、本当に堅牢な実装を取得できるとは思いません。skip()一つには、での振る舞いEOFは明確に定義されていません。is.skip(8)8バイトをスキップしてを返したい場合、再試行するかどうかを決めるのは簡単ではありません。一部の実装がで戻ることを0選択した場合、無限ループの危険があります。そして、信頼されるべきではありません。0EOFavailable()

したがって、私は次のことを提案します。

/**
 * Skips n bytes. Best effort.
 */
public static void myskip(InputStream is, long n) throws IOException {
    while(n > 0) {
        long n1 = is.skip(n);
        if( n1 > 0 ) {
            n -= n1;
        } else if( n1 == 0 ) { // should we retry? lets read one byte
            if( is.read() == -1)  // EOF
                break;
            else 
                n--;
        } else // negative? this should never happen but...
        throw new IOException("skip() returned a negative value. This should never happen");
    }
}

「本当にスキップされた」バイト数を通知する値を返す必要はありませんか?または、EOFに到達したことを通知するブール値ですか?それをしっかりと行うことはできません。たとえばskip(8)FileInputStreamオブジェクトを呼び出すと、にいる場合やファイルに2バイトしかない場合でも、8が返されます。EOFただし、このメソッドは、必要な処理を実行するという意味で堅牢です。nバイトをスキップし(可能な場合)、処理を続行します(次の読み取りが返された場合は、到達した-1ことがわかりますEOF)。

于 2013-01-18T14:26:37.150 に答える
2

nこれは、バイトをスキップするために機能しているようです:

long skippedTotal = 0;
while (skippedTotal != n) {
    long skipped = _stream.skip(n - skippedTotal);
    assert(skipped >= 0);
    skippedTotal += skipped;
    if (skipped == 0)
        break;
}
boolean skippedEnough = skippedTotal == n;

InputStreamただし、ライブラリに渡すことができるすべての実装で機能するかどうかは明らかではありません。独自のバッファ スキップ メソッドを実装する方法があるかどうか疑問に思っています。

于 2012-12-27T16:21:25.863 に答える
-1

私はこの質問に6年遅れています。

原則として、skip(int n) と readFully(int n) の間に違いはありません。スキップの場合、バイトには関心がありません。

ライブ ストリームの場合。追加された tcp ソケットまたはファイル、skip(n) は、待機するユーザーの設定に応じて 0 バイトを「スキップ」すると、ブロック (待機) できます。

EOF または -1 を返すことは、ストリームの終わりを示し、それ以降は何も起こらないため、エンド ユーザーに返す必要があります。

ファイル内のバイトを効率的にスキップするには、ランダムな io、チャネルを調べます。ただし、その最適化は、入力ストリーム全体で汎用にすることはできません。

于 2018-09-19T01:02:40.953 に答える