java:InputStream 实例的读取与 readNBytes

问题描述 投票:0回答:2

在java中,

InputStream
类有方法
read(byte[], int, int)
readNBytes(byte[], int, int)
。看起来这两种方法的功能完全相同,所以我想知道它们之间有什么区别。

java io inputstream
2个回答
4
投票

进行编辑是为了更好地了解评论中的讨论:

  • read()
    表示它尝试读取“最多
    len
    字节...但可能会读取较小的数量。此方法会阻塞,直到输入数据可用、检测到文件结尾或引发异常.”
  • readNBytes()
    表示 “阻塞,直到读取了
    len
    字节的输入数据、检测到流结束或引发异常。”

尽管 InputStream

JDK 实现
可能会为您提供两种方法相同的结果,但记录的差异意味着从它继承的其他类可能表现不同。

例如给定流

'12345<end>'
read(s,0,10)
可以返回
'123'
,而
readNbytes()
更有可能继续寻找流结束并为您提供整个内容。


原答案:

你说得对,javadoc 非常相似。如有疑问,请务必查找来源。大多数 IDE 都可以轻松附加 OpenJDK 源代码并让您深入了解它们。

这是来自

InputStream.java
readNBytes:

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
    的子类也可能有自己的重写实现。请参阅相关课程的文档/来源。

0
投票
ByteArrayInputStream.read(byte [] b, int off, int len) 实现为:

public synchronized int read (byte [] b, int off, int len){ int available=this. count - this. pos; if (len>available){ len=available; } System. arraycopy (this. buf, this. pos, b, off, len); this. pos+=len; return len; }
可以看到,当len>available时,len被截断为available,后续实际读取的字节数=available,而available表示当前流中仍然可以读取的字节数的估计值。执行int available=this后有可能。数——这个。位置;在这段代码中计算出可用性后,由于有新的数据进入ByteArrayInputStream,this.计数已被其他线程增加。比如输入流中本来有10个字节没有读到,但是我们想获取20个字节,所以我们调用了read(s,0,20)l,并且在read函数中available=this。数——这个。位置;执行后,可用的是10,但此时,另一个线程向流中添加了100个字节。因此,即使可以读取预期的 20 个字节,实际也只读取了 10 个。

我们看一下InputStream的实现。 readNBytes (byte[] b, int off, int len):

Public int readNBytes(byte[] b, int off, int len) 抛出 IOException{

物体。 checkFromIndexSize(off, len, b.length);

Int n;

整数计数;

对于 (n=0;n

计数=这个。读取 (b, off+n, len - n);

如果(数

<0){

打破;

}

}

返回n;

}

这里的for循环就是read和readNbytes的区别。 ReadNbytes并没有妥协(len=available),而是当没有足够的数据可供读取时,通过for循环停留在函数中,不继续执行。使用前面的例子,len=20,当前流中只有10个字节,第一轮循环没有读取到足够的20个字节,但是在退出readNBytes时会继续循环以确保读取到20个字节功能

总结:

区别:len只期望读入字节数,而read即使没有读满len也可能继续执行后续代码,而readNBytes则保证如果没有读满len则不执行后续代码

前提:流的长度是动态变化的,计算出的某个时刻的可用性并不完全可靠

实现方法:for循环

© www.soinside.com 2019 - 2024. All rights reserved.