Java IO 之 InputStream源码(2)
Writer:李强强
一、InputStream
InputStream是一个抽象类,即表示所有字节输入流实现类的基类。它的作用就是抽象地表示所有从不同数据源产生输入的类,例如常见的FileInputStream、FilterInputStream等。那些数据源呢?比如:
1) 字节数组(不代表String类,但可以转换)
2) String对象
3) 文件
4) 一个其他种类的流组成的序列化 (在分布式系统中常见)
5) 管道(多线程环境中的数据源)
等等
二者,注意它是属于字节流部分,而不是字符流(java.io中Reader\Writer,下面会讲到)。
FilterInputStream是为各种InputStream实现类提供的“装饰器模式”的基类。因此,可以分为原始的字节流和“装饰”过的功能封装字节流。
二、细解InputStream源码的核心
源码如下:
/*** 所有字节输入流实现类的基类*/
public abstract class SInputStream {// 缓存区字节数组最大值private static final int MAX_SKIP_BUFFER_SIZE = 2048;// 从输入流中读取数据的下一个字节,以int返回public abstract int read() throws IOException;// 从输入流中读取数据的一定数量字节,并存储在缓存数组bpublic int read(byte b[]) throws IOException {return read(b, 0, b.length);}// 从输入流中读取数据最多len个字节,并存储在缓存数组bpublic int read(byte b[], int off, int len) throws IOException {if (b == null) {throw new NullPointerException();} else if (off < 0 || len < 0 || len > b.length - off) {throw new IndexOutOfBoundsException();} else 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;}// 跳过输入流中数据的n个字节public long skip(long n) throws IOException {long remaining = n;int nr;if (n <= 0) {return 0;}int size = (int)Math.min(MAX_SKIP_BUFFER_SIZE, remaining);byte[] skipBuffer = new byte[size];while (remaining > 0) {nr = read(skipBuffer, 0, (int)Math.min(size, remaining));if (nr < 0) {break;}remaining -= nr;}return n - remaining;}// 返回下一个方法调用能不受阻塞地从此读取(或者跳过)的估计字节数public int available() throws IOException {return 0;}// 关闭此输入流,并释放与其关联的所有资源public void close() throws IOException {}// 在此输出流中标记当前位置public synchronized void mark(int readlimit) {}// 将此流重新定位到最后一次对此输入流调用 mark 方法时的位置。public synchronized void reset() throws IOException {throw new IOException("mark/reset not supported");}// 测试此输入流是否支持 mark 和 reset 方法public boolean markSupported() {return false;}}
其中,InputStream下面三个read方法才是核心方法:
public abstract int read()
抽象方法,没有具体实现。因为子类必须实现此方法的一个实现。这就是输入流的关键方法。
二者,可见下面两个read()方法都调用了这个方法子类的实现来完成功能的。
public int read(byte b[])
该方法是表示从输入流中读取数据的一定数量字节,并存储在缓存字节数组b。其效果等同于调用了下面方法的实现:
read(b, 0, b.length)
如果b
的长度为 0,则不读取任何字节并返回 0
;否则,尝试读取至少 1 字节。如果因为流位于文件末尾而没有可用的字节,则返回值 -1
;否则,至少读取一个字节并将其存储在 b
中。
思考:这时候,怪不得很多时候, b != –1 或者 b != EOF
public int read(byte b[], int off, int len)
在输入数据可用、检测到流末尾或者抛出异常前,此方法一直阻塞。
该方法先进行校验,然后校验下个字节是否为空。如果校验通过后,
如下代码:
int i = 1;
try {for (; i < len ; i++) {c = read();if (c == -1) {break;}b[off + i] = (byte)c;}
} catch (IOException ee) {
}
将读取的第一个字节存储在元素 b[off]
中,下一个存储在 b[off+1]
中,依次类推。读取的字节数最多等于 len
。设 k 为实际读取的字节数;这些字节将存储在 b[off]
到 b[off+
k-1]
的元素中,不影响 b[off+
k]
到 b[off+len-1]
的元素。
因为有上面两个read的实现,所以这里InputStream设计为抽象类。
三、小结
1. InputSream 对应着 OutputStream
2. 看源码是享受人家写代码中流露的How
3. 泥瓦匠学习的代码都在github上(同步osc git),欢迎大家点star,提意见,一起进步。地址:https://github.com/JeffLi1993
Java IO 之 InputStream源码(2)相关推荐
- Java IO 之 InputStream源码
一.InputStream InputStream是一个抽象类,即表示所有字节输入流实现类的基类.它的作用就是抽象地表示所有从不同数据源产生输入的类,例如常见的FileInputStream.Filt ...
- java io中断_JDK源码阅读:InterruptibleChannel 与可中断 IO
来源:木杉的博客 , imushan.com/2018/08/01/java/language/JDK源码阅读-InterruptibleChannel与可中断IO/ Java传统IO是不支持中断的, ...
- JAVA RGB转CMYK 源码(支持格式转换)
Java CMYK转RGB源码网上很多,但是RGB转CMYK源码网上很少,那么多是只提供公式,要么提供依赖文件不全.这两天搜索很好久,终于找到一个可行方法. 项目使用maven搭建,依赖的工具包如下. ...
- Java Review - LinkedHashMap LinkedHashSet 源码解读
文章目录 Pre 概述 数据结构 类继承关系 构造函数 方法 get() put() remove() LinkedHashSet 使用案例 - FIFO策略缓存 Pre Java Review - ...
- Java中资源文件获取源码浅析
Java中资源文件获取源码浅析 文章目录 Java中资源文件获取源码浅析 JDK11 Class.getResource(String) Class.getClassLoader().getResou ...
- 最新爱词霸 Java + mysql (含源码+数据库)
爱词霸 最新爬取 Java + mysql (含源码+数据库) 感觉金山词库的内容相对来说是最完整的!研究了一天,通过爬取html整出来的! 当然只是教程,切勿真实爬取.具体实现为什么这么做,不做阐述 ...
- java的String类源码详解
java的String类源码详解 类的定义 public final class Stringimplements java.io.Serializable, Comparable<String ...
- 死磕Java集合之BitSet源码分析(JDK18)
死磕Java集合之BitSet源码分析(JDK18) 文章目录 死磕Java集合之BitSet源码分析(JDK18) 简介 继承体系 存储结构 源码解析 属性 构造方法 set(int bitInde ...
- 死磕 java集合之ArrayDeque源码分析
问题 (1)什么是双端队列? (2)ArrayDeque是怎么实现双端队列的? (3)ArrayDeque是线程安全的吗? (4)ArrayDeque是有界的吗? 简介 双端队列是一种特殊的队列,它的 ...
最新文章
- 白宫启动AI.GOV计划,呼吁各界携手共同推进AI发展
- 全球首个AI设计药物诞生,淘宝新增垃圾识别功能……
- 1.10 访问对象的属性和行为
- 软件工程个人作业05
- 嘿,你有没有发现我今天有什么不同?
- 旅游系统_数字洛江智慧旅游系统助力提升旅游安全水平
- java 安卓下载文件_GitHub - Charay/downloadfile: 使用Retrofit2+Rxjava+Rxandroid+okhttp的方式下载文件并存储到sd卡指定目录...
- Python ord(),chr()函数
- 高颜值:Redis官方可视化工具,功能强大!
- python调用通达信函数用户指标_最新最全通达信公式教程大全(函数-指标-实例)...
- Codesys学习调试笔记1
- 打印机 计算机 usb,来古计算机-打印机端口自动识别成 USB大容量存储设备(USB mass storage device)...
- 微软Win8Server2012各版本安装密匙序列号
- 使用CSS3实现按钮特效
- 我是怎么从一家小公司通过社招去了阿里?
- linux 下的igv软件,IGV软件使用指南
- 13W 字!银四巨作:Java 进阶架构师核心手册
- 用Leangoo管理用户故事
- 小说作者推荐:春如棠合集
- ElasticSerach 出现 high disk watermark [90%] exceeded on