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)相关推荐

  1. Java IO 之 InputStream源码

    一.InputStream InputStream是一个抽象类,即表示所有字节输入流实现类的基类.它的作用就是抽象地表示所有从不同数据源产生输入的类,例如常见的FileInputStream.Filt ...

  2. java io中断_JDK源码阅读:InterruptibleChannel 与可中断 IO

    来源:木杉的博客 , imushan.com/2018/08/01/java/language/JDK源码阅读-InterruptibleChannel与可中断IO/ Java传统IO是不支持中断的, ...

  3. JAVA RGB转CMYK 源码(支持格式转换)

    Java CMYK转RGB源码网上很多,但是RGB转CMYK源码网上很少,那么多是只提供公式,要么提供依赖文件不全.这两天搜索很好久,终于找到一个可行方法. 项目使用maven搭建,依赖的工具包如下. ...

  4. Java Review - LinkedHashMap LinkedHashSet 源码解读

    文章目录 Pre 概述 数据结构 类继承关系 构造函数 方法 get() put() remove() LinkedHashSet 使用案例 - FIFO策略缓存 Pre Java Review - ...

  5. Java中资源文件获取源码浅析

    Java中资源文件获取源码浅析 文章目录 Java中资源文件获取源码浅析 JDK11 Class.getResource(String) Class.getClassLoader().getResou ...

  6. 最新爱词霸 Java + mysql (含源码+数据库)

    爱词霸 最新爬取 Java + mysql (含源码+数据库) 感觉金山词库的内容相对来说是最完整的!研究了一天,通过爬取html整出来的! 当然只是教程,切勿真实爬取.具体实现为什么这么做,不做阐述 ...

  7. java的String类源码详解

    java的String类源码详解 类的定义 public final class Stringimplements java.io.Serializable, Comparable<String ...

  8. 死磕Java集合之BitSet源码分析(JDK18)

    死磕Java集合之BitSet源码分析(JDK18) 文章目录 死磕Java集合之BitSet源码分析(JDK18) 简介 继承体系 存储结构 源码解析 属性 构造方法 set(int bitInde ...

  9. 死磕 java集合之ArrayDeque源码分析

    问题 (1)什么是双端队列? (2)ArrayDeque是怎么实现双端队列的? (3)ArrayDeque是线程安全的吗? (4)ArrayDeque是有界的吗? 简介 双端队列是一种特殊的队列,它的 ...

最新文章

  1. 白宫启动AI.GOV计划,呼吁各界携手共同推进AI发展
  2. 全球首个AI设计药物诞生,淘宝新增垃圾识别功能……
  3. 1.10 访问对象的属性和行为
  4. 软件工程个人作业05
  5. 嘿,你有没有发现我今天有什么不同?
  6. 旅游系统_数字洛江智慧旅游系统助力提升旅游安全水平
  7. java 安卓下载文件_GitHub - Charay/downloadfile: 使用Retrofit2+Rxjava+Rxandroid+okhttp的方式下载文件并存储到sd卡指定目录...
  8. Python ord(),chr()函数
  9. 高颜值:Redis官方可视化工具,功能强大!
  10. python调用通达信函数用户指标_最新最全通达信公式教程大全(函数-指标-实例)...
  11. Codesys学习调试笔记1
  12. 打印机 计算机 usb,来古计算机-打印机端口自动识别成 USB大容量存储设备(USB mass storage device)...
  13. 微软Win8Server2012各版本安装密匙序列号
  14. 使用CSS3实现按钮特效
  15. 我是怎么从一家小公司通过社招去了阿里?
  16. linux 下的igv软件,IGV软件使用指南
  17. 13W 字!银四巨作:Java 进阶架构师核心手册
  18. 用Leangoo管理用户故事
  19. 小说作者推荐:春如棠合集
  20. ElasticSerach 出现 high disk watermark [90%] exceeded on

热门文章

  1. 线性表----链式表
  2. uva 11387——The 3-Regular Graph
  3. golang实现聊天室(二)
  4. UVa12633-Super Rooks on Chessboard-容斥+FFT
  5. Qt+OpenCV打开视频文件并在窗口界面上显示
  6. 1082 射击比赛 (20 分)
  7. 一次违反常规的Java大厂面试经历,系列教学
  8. 安卓开发基础面试题,Android面试必备的集合源码详解,附小技巧
  9. 通过ceph-deploy搭建ceph 13.2.5 mimic
  10. PHP获取IP地址的方法,防止伪造IP地址注入攻击