Java:InputStream实例的read vs readNBytes

7
在Java中,InputStream类有read(byte[], int, int)readNBytes(byte[], int, int)方法。这两种方法似乎具有完全相同的功能,因此我想知道它们之间的区别是什么。

1
除了从相应的Javadocs中复制和粘贴,您还期望什么答案呢? - Elliott Frisch
3
@ElliottFrisch,我只是想知道它们之间的区别,是否有任何关于功能或实现方面的细微差别?它们的Javadocs非常相似,我无法弄清楚它们之间的区别。 - Y.S. Yuan
你不理解Javadoc的哪一部分?区别非常清楚。 - user207421
1个回答

4
  • read() 方法尝试读取 "最多 len 个字节……但可能读取更少的字节。此方法将阻塞,直到输入数据可用、检测到文件结束或抛出异常为止。"
  • readNBytes() 方法表示 "阻塞,直到读取了 len 个字节的输入数据、检测到流结束或抛出异常为止。"

尽管 InputStream 的 JDK 实现可能会为这两种方法提供相同的结果,但文档中的差异意味着继承自它的其他类可能会有不同的行为。

例如,对于流 '12345<end>'read(s,0,10) 可以返回 '123',而 readNbytes() 更可能继续查找流的结束并给出整个字符串。


原始回答:

你说得对,javadocs非常相似。当有疑问时,总是要退回到源代码。大多数IDE都可以轻松附加OpenJDK源代码,并让您深入了解它们。

这是来自InputStream.javareadNBytes

public int readNBytes(byte[] b, int off, int len) throws IOException {
    Objects.requireNonNull(b);
    if (off < 0 || len < 0 || len > b.length - off)
        throw new IndexOutOfBoundsException();
    int n = 0;
    while (n < len) {
        int count = read(b, off + n, len - n);
        if (count < 0)
            break;
        n += count;
    }
    return n;
}

正如您所看到的,它实际上执行了对read(byte[],int,int)的调用。在这种情况下的区别是,如果实际读取的字节数小于您指定的len它将尝试再次执行read()操作,直到确认实际上没有剩余可读内容为止。
编辑:请注意:
  1. 这是OpenJDK对基本InputStream的实现。其他实现可能会有所不同。
  2. InputStream的子类也可能具有自己的重写实现。请查阅相关类的文档/源代码。

2
似乎read()的javadoc只是说它尝试读取最多len个字节,而readNBytes()实际上说最多读取len个字节或者到达流的末尾为止。虽然在源代码中我们可以看到两者的行为非常相似,但文档的措辞意味着它允许覆盖read(),只要它少于len个字节就可以给你任何东西。即使在范围内有EOS,它也可能提前停止。 - NPras
非常有见地!我从未想过 read() 方法可以被覆盖,而在某些情况下 readNBytes() 会有所不同。非常感谢。 - Y.S. Yuan
1
readNBytes() 的 Javadoc 没有说“读取最多 len 个字节”。它说“从输入流中读取给定字节数组中请求的字节数”,并且进一步明确指出,除非流结束,否则将准确地读取 len 个字节。此外,这两种方法的行为并不“非常相似”。 - user207421
@user207421 说得好。我几乎可以肯定当时的简短描述确实是这样说的。我会更新的,谢谢。话虽如此,如果你看一下OpenJDK源代码,readNBytes(,,)调用了read(,,),而read()的文档说:“……阻塞直到输入数据可用、检测到流的结束或抛出异常”。这导致默认实现在read()实际执行其应该执行的操作时表现出非常相似的行为。 - NPras
它在循环中调用 read(,,)。而 read(,,) 反过来又在循环中调用 read()read() 的文档说:“阻塞直到输入数据可用、检测到流的结尾或抛出异常”。因此,如果 read() 的实现遵循其文档中描述的行为,你也会通过 read(,,) 达到 EOS。 - NPras
显示剩余4条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接