10

DataInput.skipBytes的Sun 文档指出它“尝试从输入流中跳过 n 个字节的数据,丢弃跳过的字节。但是,它可能会跳过一些较小的字节数,可能为零。这可能是由于多种条件中的任何一种;在跳过 n 个字节之前到达文件末尾只是一种可能性。”

  1. 除了到达文件末尾,为什么skipBytes()不能跳过正确的字节数?(DataInputStream我使用的将包装 aFileInputStream或 a PipedInputStream。)

  2. 如果我确实想跳过 n 个字节并抛出一个EOFException如果这导致我转到文件末尾,我应该使用readFully()并忽略生成的字节数组吗?或者,还有更好的方法?

4

5 回答 5

5

1)可能没有那么多数据可供读取(管道的另一端可能还没有发送那么多数据),并且实现类可能是非阻塞的(即它只会返回它所能返回的,而不是等待足够的数据来满足请求)。

但是,我不知道是否有任何实现实际上以这种方式运行,但该接口旨在允许它。

另一种选择只是文件在读取过程中被关闭。

2) readFully() (总是等待足够的输入,否则失败)或在循环中调用skipBytes()。我认为前者可能更好,除非阵列真的很大。

于 2008-09-09T08:33:02.903 回答
3

我今天遇到了这个问题。它正在读取虚拟机上的网络连接,所以我想可能有很多原因导致这种情况发生。我通过简单地强制输入流跳过字节直到它跳过我想要的字节数来解决它:

int byteOffsetX = someNumber; //n bytes to skip
int nSkipped = 0;

nSkipped = in.skipBytes(byteOffsetX);
while (nSkipped < byteOffsetX) {
    nSkipped = nSkipped + in.skipBytes(byteOffsetX - nSkipped);
}
于 2010-10-20T12:41:28.303 回答
2

事实证明,readFully() 增加了比我愿意忍受的更多的性能开销。

最后我妥协了:我调用了一次 skipBytes(),如果返回的字节数少于正确的字节数,我就调用 readFully() 来获取剩余的字节。

于 2008-09-09T13:08:43.990 回答
1

乔什·布洛赫最近公布了这一点。这是一致的, InputStream.read 不能保证读取尽可能多的字节。但是,作为 API 方法,它是完全没有意义的。InputStream 也应该有 readFully。

于 2008-09-09T11:08:00.397 回答
0

根据文档,readFully()这是唯一有效且保证有效的方法。

实际的 Oracle 实现是......令人困惑:

public final int skipBytes(int n) throws IOException {
    int total = 0;
    int cur = 0;

    while ((total<n) && ((cur = (int) in.skip(n-total)) > 0)) {
        total += cur;
    }

    return total;
}

为什么在与具有基本相同的合同skip()时循环调用?如果以下两个都成立,那么以这种方式实现它是非常有意义的:保证在 EOF 上跳过少于请求的内容,保证尽可能跳过至少一个字节(就像这样做一样)。skipBytes()skip()skipBytes() skip()read()

更糟糕的是,它skip()实际上是使用 实现的read(),这意味着它实际上完成了这项工作。它只是不承诺这样做,这意味着其他实现可能无法这样做(如果在未来的版本中更改,即使是 Oracle 也可能在未来失败)。

为了完全安全: call readBytes(),如果它不起作用,分配一个临时缓冲区并调用readFully()(如果需要跳过任意大量数据的能力,请在此处使用循环)。

另一方面,skipBytes()循环调用是没有意义的。至少在 Oracle 实现中,因为它已经是一个循环。

于 2020-04-16T13:18:21.383 回答