zoukankan      html  css  js  c++  java
  • 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 

  • 相关阅读:
    转:[Silverlight入门系列]使用MVVM模式(9): 想在ViewModel中控制TreeView节点展开?
    C#线程同步方法——Monitor
    转:Mongodb源码分析之Replication模式
    转:Mysql使用主从复制机制(replication)
    Ruby IDE
    转:ASP.NET MVC4细嚼慢咽---(5)js css文件合并
    转:ASP.NET MVC4细嚼慢咽---(6)全局过滤器
    转:WCF服务开发与调用的完整示例
    转:WF工作流技术内幕 —— 通过Web服务调用Workflow工作流(开发持久化工作流)
    汇总高效的卷积神经网络结构[转载]
  • 原文地址:https://www.cnblogs.com/nolan4954/p/9262775.html
Copyright © 2011-2022 走看看