//read(byte[] b, int off, int len)
public int read(byte[] b, int off, int len) throws IOException {
Objects.checkFromIndexSize(off, len, b.length);
if (len == 0) {
return 0;
}
int c = read();
if (c == -1) {
return -1;
}
b[off] = (byte)c;
int i = 1;
try {
for (; i < len ; i++) {
c = read();
if (c == -1) {
break;
}
b[off + i] = (byte)c;
}
} catch (IOException ee) {
}
return i;
}
//readNBytes(byte[] b, int off, int len)
public int readNBytes(byte[] b, int off, int len) throws IOException {
Objects.checkFromIndexSize(off, len, b.length);
int n = 0;
while (n < len) {
int count = read(b, off + n, len - n);
if (count < 0)
break;
n += count;
}
return n;
}
除了文本末尾再调用时,read()返回值是-1,readNBytes()返回值是0,还有什么区别?
在 Java 的 InputStream 中,read() 和 readNBytes() 方法有一些关键的区别。你所提供的代码实现了两个方法:一个是 read(byte[] b, int off, int len),另一个是 readNBytes(byte[] b, int off, int len)。
read(byte[] b, int off, int len) 方法
read(byte[] b, int off, int len) 方法的作用是从输入流中读取最多 len 个字节并将它们存储在字节数组 b 中,从索引 off 开始。此方法会返回实际读取的字节数,如果在读取第一个字节时遇到文件末尾,则返回 -1。
这个方法在实现上有以下几点:
一次最多读取 len 个字节:即使调用者希望读取 len 个字节,这个方法也可能读取少于 len 个字节,具体取决于输入流的可用数据。
返回实际读取的字节数:这个方法返回的是实际读取的字节数。如果在读取第一个字节时遇到文件末尾,返回 -1。
readNBytes(byte[] b, int off, int len) 方法
readNBytes(byte[] b, int off, int len) 方法的作用是从输入流中读取恰好 len 个字节,除非到达流的末尾。在这种情况下,它会读取尽可能多的字节。这方法会返回实际读取的字节数。
这个方法在实现上有以下几点:
尽量读取 len 个字节:这个方法会在内部调用 read(byte[] b, int off, int len) 多次,直到读取到恰好 len 个字节或到达文件末尾为止。
返回实际读取的字节数:如果在读取过程中到达文件末尾,返回实际读取的字节数。返回值为 0 表示没有读取到任何字节,且文件已到末尾。
关键区别
读取的字节数:
read(byte[] b, int off, int len):一次最多读取 len 个字节,但实际读取的字节数可能少于 len 个字节。
readNBytes(byte[] b, int off, int len):尽量读取 len 个字节,可能多次调用 read(byte[] b, int off, int len) 直到读取到 len 个字节或到达文件末尾。
返回值:
read(byte[] b, int off, int len):返回实际读取的字节数,如果在读取第一个字节时到达文件末尾,返回 -1。
readNBytes(byte[] b, int off, int len):返回实际读取的字节数,如果到达文件末尾,返回实际读取的字节数(可能为 0)。
行为上的区别:
read(byte[] b, int off, int len):一次调用尽可能多地读取字节,但可能少于 len 个字节。
readNBytes(byte[] b, int off, int len):确保尽量读取 len 个字节,除非流的末尾被提前到达。
总结:readNBytes 方法相比于 read 方法更加 "贪心",它会尝试读取尽可能多的字节直到达到指定的长度或者到达输入流的末尾,而 read 方法只会尝试一次读取尽可能多的字节,因此 readNBytes 方法在实现上更加复杂,因为它需要在内部循环调用 read 方法来实现这一点。
除了到达文本末尾,什么情况下read()读的字节会少于len,能否举个例子
read() 读的字节少于 len 很常见,比如当你在读数据的时候,同时有一个进程/线程在写数据(比如标准输入/输出、网络通信),这时当你 read(buf, 0, 1024) 发现实际读取小于 1024,然而并未到达末尾,因为可能是你读取的速度快于写入的速度。下次调用 read(buf, 0, 1024) 时仍可读取到数据。
一般在网络通信中会先传一个 Content-Length 的头信息,表示数据实际内容的长度,可以以此判断该条信息是否读取完毕,避免因 read() 未读到目标长度的数据而误判读取完毕。