Java I/O系列(一)InputStream与OutputStream源码分析及理解

1. InputStream

定义


 字节输入流,是一个抽象类,核心是通过read()方法,从数据源中读取一个个字节出来,另有skip,mark功能

 

核心源码理解


源码:

 1 public abstract int read() throws IOException; 

理解:

1. 抽象方法,必须由子类实现;从什么地方读?数据源来自哪里?这个是由子类提供的,如FileInputStream是从文件中读,ByteArrayInputStream是从byte数组中读...

2. 每次读取都只会读取一个字节,一个byte出来,是有顺序的,读完这个字节,会自动跳到下一个字节等待读取

3. 注意返回值的定义是int,不是byte:如果有byte可读,就返回这个byte对应的无符号类型的值(0 - 255),返回值可以理解成某个“字符”的ASCII码值(如读取到A了,那么就会返回65)如果没有byte可读就直接返回-1

 

源码:

 1 public int read(byte b[], int off, int len) throws IOException {
 2         if (b == null) {
 3             throw new NullPointerException();
 4         } else if (off < 0 || len < 0 || len > b.length - off) {
 5             throw new IndexOutOfBoundsException();
 6         } else if (len == 0) {
 7             return 0;
 8         }
 9 
10         int c = read();
11         if (c == -1) {
12             return -1;
13         }
14         b[off] = (byte)c;
15 
16         int i = 1;
17         try {
18             for (; i < len ; i++) {
19                 c = read();
20                 if (c == -1) {
21                     break;
22                 }
23                 b[off + i] = (byte)c;
24             }
25         } catch (IOException ee) {
26         }
27         return i;
28     }

 理解:

1. 这个方法比较好理解,循环调用read()方法,将读取到的int转换成byte,然后再放到参数b的特定位置(从off开始放,放len个,当然可能放不满len个,是等待读取的字节数而定);注意子类可能会重写这个方法,会有另外的实现

2. 返回值是实际读出来的字节数,如果没有则返回-1 

 

2. OutPutStream

定义


 字节输出流,也是一个抽象类,核心是通过write()方法,一个一个字节的写入到目的数据源中(由子类决定)

 

核心源码理解


源码:

 1 public abstract void write(int b) throws IOException; 

理解:

1. 抽象方法,必须由子类实现;写入到哪儿呢,由子类决定

2. 参数b是作为要写入的数据,是int类型不是byte类型;因为int是占4个字节共32位,这里规定的是取低8位,忽略高24位,所以最后写入的是一个字节;参数可以理解成某个ASCII码值的十进制,写入的就是对应的“字符”(如b=65时,写入的就是A)

 

源码:

 1 public void write(byte b[], int off, int len) throws IOException {
 2         if (b == null) {
 3             throw new NullPointerException();
 4         } else if ((off < 0) || (off > b.length) || (len < 0) ||
 5                    ((off + len) > b.length) || ((off + len) < 0)) {
 6             throw new IndexOutOfBoundsException();
 7         } else if (len == 0) {
 8             return;
 9         }
10         for (int i = 0 ; i < len ; i++) {
11             write(b[off + i]);
12         }
13     }

理解:

1. 循环调用write()方法,将b[off] 到 b[off + len - 1] 的值写入到目的数据源

 

3. 总结:


1. 细心的可能会发现,read()方法返回值的范围是0 - 255,而byte本身范围是-128 - 127, 这样的转换其实是有符号byte类型到无符号类型的转换,做法是 int a = b & oxff, 其中b是有符号类型的byte   具体参考:https://www.jianshu.com/p/db85f033e75c

2. skip比较简单,其实现是将待跳过的部分读取出来而不使用;mark与reset结合使用都没有给出默认实现,由子类实现

3. 注意write(int b) 方法,是取b的低8位,忽略b的高24位 

 

4. 问题:


 1. 欢迎大家提出问题,共同交流学习!

 

5. 示例:


 

6. 参考:


 1. https://www.jianshu.com/p/db85f033e75c 

 

posted @ 2018-07-04 13:05  nolan4954  阅读(573)  评论(0编辑  收藏  举报