在java.io.InputStream及其子类型中可靠地跳过数据

时间:2012-12-27 16:18:40

标签: java stream inputstream java-io skip

我正在处理二进制流,需要有效跳过我不感兴趣的一系列数据,以及一些将要处理的数据。

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

  

从此输入流中跳过并丢弃n个字节的数据。由于各种原因,跳过方法可能最终跳过一些较小数量的字节,可能为0.这可能是由许多条件中的任何一个引起的;在跳过n个字节之前到达文件末尾只有一种可能性。返回跳过的实际字节数。

我需要知道发生了两件事之一:

  1. 小溪已结束
  2. 跳过了字节
  3. 足够简单。但是,此描述中提供的宽大意味着,例如,BufferedInputStream可以跳过几个字节并返回。当然,它告诉我它只是跳过了那几个,但不清楚为什么。

    所以我的问题是:您是否能够以这样的方式使用InputStream.skip(long):您知道流何时结束或跳过成功完成?

3 个答案:

答案 0 :(得分:9)

我认为我们无法获得真正的强大的实现,因为skip()方法合同相当奇怪。首先,EOF的行为没有明确定义。如果我想跳过8个字节并且is.skip(8)返回0,那么判断我是否应该再次尝试并不容易,如果某些实现选择在EOF时返回0,则存在无限循环的危险。 available()也不值得信任。

因此,我提出以下建议:

/**
 * Skips n bytes. 
 */
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)it will return 8即使我们处于EOF,或者文件只有2个字节。但是这个方法在我们想做的事情上是健壮的:跳过n字节(如果可能的话)并让我继续处理它(如果我的下一次读取返回-1我会知道已达到EOF)

答案 1 :(得分: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的所有实现。我想知道实现我自己的缓冲跳过方法是否可行。

答案 2 :(得分:0)

这个问题我迟到了6年。

原则上,skip(int n)之间没有区别 和readFully(int n)。在跳过情况下,您不感兴趣  以字节为单位。

对于实时流,即TCP套接字或一个文件是 附加到skip(n)一旦阻塞就可以阻塞 «跳过»0个字节,具体取决于要等待的用户。

取回EOF或-1表示末尾 流,并将其返回给最终用户 因为没有其他事情会发生。

要有效地跳过文件中的字节,我会 探索随机io,频道。但是这种优化不可能 在所有输入流中通用。