【给JDK IO源码加点注释】01 InputStream、OutputStream

InputStream

  1 package java.io;
  2 
  3 import java.util.Arrays;
  4 import java.util.Objects;
  5 抽象方法实现了closeable接口,可以在try with resource中使用。
  6 public abstract class InputStream implements Closeable {
  7     跳过缓存数组的最大值
  8     private static final int MAX_SKIP_BUFFER_SIZE = 2048;
  9     默认缓存数组大小
 10     private static final int DEFAULT_BUFFER_SIZE = 8192;
 11 
 12     /**
 13      *读取流中下一个字节(0-255)。如果读完返回-1.此方法会导致阻塞。
 14      *
 15      * 抽象方法,子类必须提供此方法的实现.
 16      *
 17      * @return     流中下一个字节或者-1(当读取完时)
 18      *
 19      * @exception  IOException  if an I/O error occurs.
 20      */
 21     public abstract int read() throws IOException;
 22 
 23     /**
 24      
 25      *试图读入多个字节,存入字节数组b,返回实际读入的字节数。
 26         *如果传递的是一个空数组(注意数组长度可以为0,即空数组。比如 byte[] b = new  byte[0]; 或者byte[] b = {};)
 27         *那么什么也没读入,返回0.
 28    *如果到达流尾部,没有字节可读,返回-1;如果上面两种情况都没有出现,并且没有I/O错误,则至少有1个字节被读入,存储到字节数组b中。
 29         *实际读入的第一个字节存在b[0],往后一次存入数组,读入的字节数最多不能超过数组b的长度。
 30         *如果读入的字节数小于b的长度,剩余的数组元素保持不 变。具体地,如果读入的字节数为k,则k个字节分别存在 b[0]到b[k-1],而b[k]到                        *b[b.length-1]保持原来的数据。
 31      *
 32      * 此方法与read(b, 0, b.length)效果相同
 33      *
 34      * @param      存储读取字节的数组
 35      * @return     0 如果传入的数组为空
 36      *             -1 此输入流没有字节可读取了
 37      *             int 实际读取的字节数
 38      * @exception  IOException 
 39      * @exception  NullPointerException  传入数组b[]没有初始化
 40      */
 41     public int read(byte b[]) throws IOException {
 42         return read(b, 0, b.length);
 43     }
 44 
 45     /**
 46      *读入的数据存储到b数组是从off开始。len是试图读入的字节数,返回的是实际读入的字节数。
 47          *如果len=0,则什么也不读入,返回0;如果遇到流尾部,返回-1.否则至少读入一个字节。
 48      *
 49      * 第一个读取的字节存储到 b[off]中 , 下一个在b[off+1],直到b[off+len-1](数据量大于len时).
 50      *
 51      *
 52      * @param      b     存储读取字节的数组
 53      * @param      off   开始存放第一个读取数据的位置
 54      *                   
 55      * @param      len   最大的字节数.
 56      * @return     0    如果len为0
 57      *             -1    流中已经没有数据。
 58      *             int    实际读取的字节数(最大为len)
 59      * @exception  IOException 
 60      * @exception  NullPointerException b[]为null
 61      * @exception  IndexOutOfBoundsException off,len为负数 或者 len大于b.length - off
 62          */
 63     public int read(byte b[], int off, int len) throws IOException {
 64         if (b == null) {
 65             throw new NullPointerException();
 66         } else if (off < 0 || len < 0 || len > b.length - off) {
 67             throw new IndexOutOfBoundsException();
 68         } else if (len == 0) {
 69             return 0;
 70         }
 71 
 72         int c = read();
 73         if (c == -1) {
 74             return -1;
 75         }
 76         b[off] = (byte)c;
 77 
 78         int i = 1;
 79         try {
 80             for (; i < len ; i++) {
 81                 c = read();
 82                 if (c == -1) {
 83                     break;
 84                 }
 85                 b[off + i] = (byte)c;
 86             }
 87         } catch (IOException ee) {
 88         }
 89         return i;
 90     }
 91 
 92     /**
 93      * 缓存数组最大值
 94      */
 95     private static final int MAX_BUFFER_SIZE = Integer.MAX_VALUE - 8;
 96 
 97     /**
 98      * 读取流中剩下的全部字节
 99      *
100      * 当流中没有数据时返回空的数组
101      *
102      *
103      * @return byte[] 流中全部字节
104      * @throws IOException if an I/O error occurs
105      * @throws OutOfMemoryError 当流中字节数大于Integer.MAX_VALUE - 8时,即数据大于2gb
106      *
107      * jdk9新增的方法
108      */
109     public byte[] readAllBytes() throws IOException {
110         //创建一个缓存数组,用于存放读取的数据。
111         byte[] buf = new byte[DEFAULT_BUFFER_SIZE];
112         //读取的数据量
113         int capacity = buf.length;
114         //已经读取数据量
115         int nread = 0;
116         //一次读取的数量
117         int n;
118         //死循环读取数据相当于while(true)
119         for (;;) {
120             // 当流中还有数据,缓存数组未读满时,调用read方法读取数据到buf中
121             while ((n = read(buf, nread, capacity - nread)) > 0)
122                 nread += n;
123 
124             // 流中数据已读完,跳出死循环
125             if (n < 0)
126                 break;
127 
128             // 未跳出说明缓存数组已满需要扩大数组
129             if (capacity <= MAX_BUFFER_SIZE - capacity) {
130                 capacity = capacity << 1;
131             } else {
132                 if (capacity == MAX_BUFFER_SIZE)
133                     throw new OutOfMemoryError("Required array size too large");
134                 capacity = MAX_BUFFER_SIZE;
135             }
136             buf = Arrays.copyOf(buf, capacity);
137         }
138         //返回
139         return (capacity == nread) ? buf : Arrays.copyOf(buf, nread);
140     }
141 
142     /**
143      *  从 InputStream 中读取指定数量的字节到数组中与read(byte[] b,int off ,int len)相似
144      */
145     public int readNBytes(byte[] b, int off, int len) throws IOException {
146         Objects.requireNonNull(b);
147         if (off < 0 || len < 0 || len > b.length - off)
148             throw new IndexOutOfBoundsException();
149         int n = 0;
150         while (n < len) {
151             int count = read(b, off + n, len - n);
152             if (count < 0)
153                 break;
154             n += count;
155         }
156         return n;
157     }
158 
159     /**
160      * 试图跳过n个字节,返回实际跳过字节数的方法
161      * 例如流中只有6个字节,传入7只能跳过6,所以返回6.
162      * @param      n   试图跳过的字节数.
163      * @return     the 实际跳过的字节数.
164      * @throws     IOException .
165      */
166     public long skip(long n) throws IOException {
167         
168         long remaining = n;
169         int nr;
170 
171         if (n <= 0) {
172             return 0;
173         }
174 
175         int size = (int)Math.min(MAX_SKIP_BUFFER_SIZE, remaining);
176         byte[] skipBuffer = new byte[size];
177         while (remaining > 0) {
178             nr = read(skipBuffer, 0, (int)Math.min(size, remaining));
179             if (nr < 0) {
180                 break;
181             }
182             remaining -= nr;
183         }
184 
185         return n - remaining;
186     }
187 
188     /**
189      * 返回流中可读取的字节数,具体由子类实现
190      */
191     public int available() throws IOException {
192         return 0;
193     }
194 
195     /**
196      * 关闭流
197      * @exception  IOException  if an I/O error occurs.
198      */
199     public void close() throws IOException {}
200 
201     /**
202      * 在当前位置定义一个标记,使用reset可以会到标记处,可以进行数据的重复读取。
203      * 
204      *
205      * <p> Marking a closed stream should not have any effect on the stream.
206      *
207      * <p> The <code>mark</code> method of <code>InputStream</code> does
208      * nothing.
209      *
210      * @param   readlimit   在标记后最大可读取数,超过此数字,标记过期,不允许reset。
211      *                      
212      * @see     java.io.InputStream#reset()
213      */
214     public synchronized void mark(int readlimit) {}
215 
216     /**
217      * 用于重定位到最近的标记。如果在这之前mark方法从来没被调用,或者标记已经无效,在抛出IOException。
218          *   如果没有抛出这个异常,将当前位置重新定位到最近的标记位置。
219      *
220      * @exception  如果流未被标记。
221      * @see     java.io.InputStream#mark(int)
222      * @see     java.io.IOException
223      */
224     public synchronized void reset() throws IOException {
225         throw new IOException("mark/reset not supported");
226     }
227 
228     /**
229      *返回流是否支持标记,默认未false。
230      */
231     public boolean markSupported() {
232         return false;
233     }
234 
235     /**
236      * 读取流中所有数据并写入到传入的输出流中
237      * @param  目标输出流
238      * @return 写入到输出流中的数据量
239      * @throws IOException 
240      * @throws NullPointerException 当out为null时
241      *
242      * @since 9
243      */
244     public long transferTo(OutputStream out) throws IOException {
245         Objects.requireNonNull(out, "out");
246         long transferred = 0;
247         byte[] buffer = new byte[DEFAULT_BUFFER_SIZE];
248         int read;
249         while ((read = this.read(buffer, 0, DEFAULT_BUFFER_SIZE)) >= 0) {
250             out.write(buffer, 0, read);
251             transferred += read;
252         }
253         return transferred;
254     }
255 }

OutputStream

package java.io;
/**
* 输出字节流抽象类
*/
public abstract class OutputStream implements Closeable, Flushable {
    /**
     * 向流中写入特定的字节,截取低8位,忽略高24位。
     *
     * @param      b   待写入字节。
     * @exception  IOException  
     */
    public abstract void write(int b) throws IOException;

    /**
     * 向流中写入一个字节数组。
     *
     * @param      b   待写入字节数组。
     * @exception  IOException  
     * @see        java.io.OutputStream#write(byte[], int, int)
     */
    public void write(byte b[]) throws IOException {
        write(b, 0, b.length);
    }

    /**
     * 将 b[]中off开始len个字节写入输出流中,即b[off]到b[off+len-1]。
     * <p>
     * 如果b为null会抛出空指针异常
     * 如果off,len为负,或者off+len比数组的长度大将抛出IndexOutOfBoundsException
     *
     * @param      b     字节数组
     * @param      off   写入的其实位置
     * @param      len   写入的字节数
     * @exception  IOException 
     */
    public void write(byte b[], int off, int len) throws IOException {
        if (b == null) {
            throw new NullPointerException();
        } else if ((off < 0) || (off > b.length) || (len < 0) ||
                   ((off + len) > b.length) || ((off + len) < 0)) {
            throw new IndexOutOfBoundsException();
        } else if (len == 0) {
            return;
        }
        for (int i = 0 ; i < len ; i++) {
            write(b[off + i]);
        }
    }


    public void flush() throws IOException {
    }

    /**
     * 关闭此输出流并释放资源。
     * @exception  IOException
     */
    public void close() throws IOException {
    }

}

 

posted @ 2018-06-28 18:49  Panic1  阅读(86)  评论(0)    收藏  举报