代码拉取完成,页面将自动刷新
import java.io.Closeable;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Objects;
public abstract class MyInputStream implements Closeable {
// MAX_SKIP_BUFFER_SIZE 用于确定跳过时使用的最大缓冲区大小
private static final int MAX_SKIP_BUFFER_SIZE = 2048;
// 默认的buffer size
private static final int DEFAULT_BUFFER_SIZE = 8192;
// JDK11中增加了一个nullInputStream,即空模式实现,以便可以直接调用而不用判空(可以看如下的补充说明)
/**
* 从输入流中读取下一个字节的数据。值作为范围为 0 到 255 的 int 返回。
* 如果由于到达流的末尾而没有可用的字节,则返回 -1。
* 此方法将阻塞,直到有输入数据可用、检测到流的末尾或引发异常。
*
* <p> 子类必须提供此方法的实现。
*
* @return 返回下一个字节数据,如果到达流末尾则返回 -1。
* @exception IOException 如果发生 I/O 错误。
* 读取下一个字符数据,没有返回-1
*/
public abstract int read() throws IOException;
/**
* 从输入流中读取若干字节并将其存储到缓冲区数组 b 中。
* 返回读取的字节数。如果 b 的长度为 0,则不读取任何字节并返回 0。
* 如果没有可用的字节,因为流到达文件的末尾,则返回 -1。
* 否则,将至少读取一个字节并存储到 b 中。
*将读取到的数据放在 byte 数组中,该方法实际上调用read(byte b[], int off, int len)方法
* @param b 将数据读取到其中的缓冲区。
* @return 返回读取到缓冲区的总字节数,如果到达流末尾则返回 -1。
* @exception IOException 如果由于任何原因第一个字节无法读取,流已关闭,或发生其他 I/O 错误。
* @exception NullPointerException 如果 b 为 null。
*/
public int read(byte b[]) throws IOException {
return read(b, 0, b.length);
}
/**
* 从输入流中读取最多 len 个字节的数据到字节数组中。
* 此方法将阻塞,直到有输入数据可用、检测到文件结束或引发异常。
*
* @param b 将数据读取到其中的缓冲区。
* @param off 在数组 b 中开始写入数据的偏移量。
* @param len 要读取的最大字节数。
* @return 返回读取到缓冲区的总字节数,如果到达流末尾则返回 -1。
* @exception IOException 如果由于任何原因第一个字节无法读取,流已关闭,或发生其他 I/O 错误。
* @exception NullPointerException 如果 b 为 null。
* @exception IndexOutOfBoundsException 如果 off 或 len 为负数,或 len 大于 b.length - off。
*/
public int read(byte b[], int off, int len) throws IOException {
// 检查边界
//Objects.checkFromIndexSize(off, len, b.length);
//读取最大字节数为0返回
if (len == 0) {
return 0;
}
// 读取下一个字节
int c = read();//
/*
这里的设计可以提前判断流状态,提前返回,提高效率
*/
if (c == -1) { // 读到stream末尾,则返回读取的字节数量为-1
return -1;
}
///off 作为偏移量参数,指定了数据在数组 b 中的起始存储位置
b[off] = (byte)c;// 将读取到的字节转换为byte类型,存入指定的数组位置b[off]
// i用来记录取了多少个字节
int i = 1;
try {
// 循环读取
for (; i < len ; i++) {
c = read();
if (c == -1) {// 读到stream末尾,则break
break;
}
b[off + i] = (byte)c;
}
} catch (IOException ee) {
}
// 返回读取到的字节个数
return i;
}
/**
* 跳过并丢弃此输入流中的 n 个字节。
* 该方法可能跳过更少的字节(甚至为 0),负数返回 0。返回实际跳过的字节数。
*
* @param n 要跳过的字节数。
* @return 实际跳过的字节数。
* @exception IOException 如果流不支持跳过操作,或发生其他 I/O 错误。
*/
public long skip(long n) throws IOException {
// 剩余要跳过的字节数
long remaining = n;
int nr;
// 如果请求跳过的字节数小于等于0,则直接返回0
if (n <= 0) {
return 0;
}
// 设置缓冲区大小,取最小值
// 使得最大不超过MAX_SKIP_BUFFER_SIZE,避免过大消耗内存
int size = (int)Math.min(MAX_SKIP_BUFFER_SIZE, remaining);
// 用于跳过字节的缓冲区
byte[] skipBuffer = new byte[size];
// 循环读取,直到跳过指定字节数或到达流末尾
while (remaining > 0) {
// 从流中读取最多size或remaining字节,读入skipBuffer,偏移量从0开始
nr = read(skipBuffer, 0, (int)Math.min(size, remaining));
// 如果读取结果为负,表示流已结束,跳出循环
if (nr < 0) {
break;
}
// 更新剩余字节数
remaining = remaining - nr;
}
// 返回实际跳过的字节数(即总字节数n减去剩余字节数remaining)
/*
假设 n = 15,MAX_SKIP_BUFFER_SIZE = 8,并且输入流中共有 10 个字节可供读取。
第一次循环:remaining = 15,缓冲区大小 size = 8。调用 read(skipBuffer, 0, 8),假设读取 8 个字节,remaining 变为 15 - 8 = 7。
第二次循环:remaining = 7,缓冲区大小 size = 7。调用 read(skipBuffer, 0, 7),假设读取了 2 个字节(流中只剩 2 个字节),remaining 变为 7 - 2 = 5。
第三次循环:remaining = 5,调用 read(skipBuffer, 0, 5),此时返回 -1(流末尾),循环终止。
也就是read读到了文件末尾了,你remaining都没读到n的大小-就有了实际跳过数
*/
return n - remaining;
}
/**
* 返回在不阻塞的情况下可以从此输入流中读取的字节数的估计值。
*
* @return 可读取(或跳过)字节数的估计值,当到达输入流末尾时为 0。
* @exception IOException 如果发生 I/O 错误。
*/
public int available() throws IOException {
return 0;
}
/**
* 关闭此输入流并释放与流关联的任何系统资源。
*
* @exception IOException 如果发生 I/O 错误。
*/
public void close() throws IOException {}
/**
* 标记输入流中的当前位置。后续调用 reset 方法将重新定位此流。
* mark 方法不进行任何操作。
*
* @param readlimit 在标记位置失效之前可以读取的最大字节数。
*/
public synchronized void mark(int readlimit) {}
/**
* 将流重新定位到最后一次调用 mark 方法时的位置。
* 此方法对 InputStream 类无效,仅抛出 IOException。
* 标记读取位置,下次还可以从这里开始读取,使用前要看当前流是否支持,可以使用 markSupport() 方法判断
* @exception IOException 如果未标记或标记已失效。
*/
// 重置读取位置为上次 mark 标记的位置
public synchronized void reset() throws IOException {
throw new IOException("mark/reset not supported");
}
// 判断当前流是否支持标记流,和上面两个方法配套使用。默认是false,由子类方法重写
/**
* 测试此输入流是否支持 mark 和 reset 方法。
*
* @return 如果此流实例支持 mark 和 reset 方法则返回 true;否则返回 false。
*/
public boolean markSupported() {
return false;
}
}
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。