在java中,
InputStream
类有方法read(byte[], int, int)
和readNBytes(byte[], int, int)
。看起来这两种方法的功能完全相同,所以我想知道它们之间有什么区别。
进行编辑是为了更好地了解评论中的讨论:
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(),直到确认实际上没有任何内容可供读取为止。
编辑:请注意
InputStream
的实现。其他人可能会有所不同。InputStream
的子类也可能有自己的重写实现。请参阅相关课程的文档/来源。
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
如果(数
<0){
打破;}
}
返回n;
}
这里的for循环就是read和readNbytes的区别。 ReadNbytes并没有妥协(len=available),而是当没有足够的数据可供读取时,通过for循环停留在函数中,不继续执行。使用前面的例子,len=20,当前流中只有10个字节,第一轮循环没有读取到足够的20个字节,但是在退出readNBytes时会继续循环以确保读取到20个字节功能
总结:
区别:len只期望读入字节数,而read即使没有读满len也可能继续执行后续代码,而readNBytes则保证如果没有读满len则不执行后续代码
前提:流的长度是动态变化的,计算出的某个时刻的可用性并不完全可靠
实现方法:for循环