簡體   English   中英

在java.io.InputStream及其子類型中可靠地跳過數據

[英]Robust skipping of data in a java.io.InputStream and its subtypes

我正在處理二進制流,需要有效地跳過我不感興趣的一系列數據,以及一些將被處理的數據。

InputStream.skip(long)在保證方面沒有太大作用:

跳過並丟棄此輸入流中的n個字節的數據。 由於各種原因,跳過方法可能最終跳過一些較小數量的字節,可能為0.這可能是由許多條件中的任何一個引起的; 在跳過n個字節之前到達文件末尾只有一種可能性。 返回跳過的實際字節數。

我需要知道發生了兩件事之一:

  1. 小溪結束了
  2. 跳過了字節

很簡單。 但是,此描述中提供的寬大意味着,例如, BufferedInputStream可以跳過幾個字節並返回。 當然,它告訴我它只是跳過了那幾個,但不清楚為什么。

所以我的問題是:你能否以你知道流何時結束或跳過成功的方式使用InputStream.skip(long)

我認為我們不能得到一個非常強大的實現,因為skip()方法合同相當奇怪。 首先, EOF的行為沒有明確定義。 如果我想跳過8個字節並且is.skip(8)返回0 ,那么判斷我是否應該再次嘗試並不容易,如果某個實現選擇在EOF返回0 ,則存在無限循環的危險。 並且available()也不值得信任。

因此,我提出以下建議:

/**
 * 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? 我們不能以強有力的方式做到這一點。 例如,如果我們為FileInputStream對象調用skip(8) ,即使我們處於EOF ,或者文件只有2個字節, 它也將返回8 但是這個方法在我們想做的事情上是健壯的:跳過n個字節(如果可能的話)並讓我繼續處理它(如果我的下一個讀取返回-1我將知道已達到EOF )。

這似乎適用於跳過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實現。 我想知道實現我自己的緩沖跳過方法是否可行。

這個問題我遲到了6年。

原則上,skip(int n)和readFully(int n)之間沒有區別。 在跳過的情況下,您對字節不感興趣。

對於直播,即。 tcp套接字或附加到的文件,skip(n)一旦“跳過”0字節就會阻塞(等待),具體取決於用戶的等待時間。

返回EOF或-1表示流的結束,應該返回給最終用戶,因為在該點之后不會發生任何其他事情。

為了有效地跳過文件中的字節,我將探索隨機io,channel。 但是這種優化不能在任何輸入流中變得通用。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM