概述
基于jdk1.8.0_77。
InputStream
MAX_SKIP_BUFFER_SIZE
MAX_SKIP_BUFFER_SIZE:最大跳过字节数组为2048。当要跳过当前输入流的一段时,首先定义一个数组,不断的去读取数据,直到读取了传入的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; }
read抽象方法
read():抽象方法,读入下一个字节,返回的值为 0-255 之间的一个数字,如果读到了流的结尾,读不出数据,则返回 -1,
/** * Reads the next byte of data from the input stream. The value byte is * returned as an <code>int</code> in the range <code>0</code> to * <code>255</code>. If no byte is available because the end of the stream * has been reached, the value <code>-1</code> is returned. This method * blocks until input data is available, the end of the stream is detected, * or an exception is thrown. * * <p> A subclass must provide an implementation of this method. * * @return the next byte of data, or <code>-1</code> if the end of the * stream is reached. * @exception IOException if an I/O error occurs. */ public abstract int read() throws IOException;
read重载方法
从数组的 off 位置读入 len 长度的字节数据到 b[] 数组中,最后返回读取的字节数。
public 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; }
从流中读出数据到数组中
public int read(byte b[]) throws IOException { return read(b, 0, b.length); }
available
返回一个可以读或者忽略的估计值,但是不准确。具体使用没有遇到过。实现应该是在其子类中实现,子类可能会抛出异常,所以需要先在父类中定义好。
/** * Returns an estimate of the number of bytes that can be read (or * skipped over) from this input stream without blocking by the next * invocation of a method for this input stream. The next invocation * might be the same thread or another thread. A single read or skip of this * many bytes will not block, but may read or skip fewer bytes. * * <p> Note that while some implementations of {@code InputStream} will return * the total number of bytes in the stream, many will not. It is * never correct to use the return value of this method to allocate * a buffer intended to hold all data in this stream. * * <p> A subclass' implementation of this method may choose to throw an * {@link IOException} if this input stream has been closed by * invoking the {@link #close()} method. * * <p> The {@code available} method for class {@code InputStream} always * returns {@code 0}. * * <p> This method should be overridden by subclasses. * * @return an estimate of the number of bytes that can be read (or skipped * over) from this input stream without blocking or {@code 0} when * it reaches the end of the input stream. * @exception IOException if an I/O error occurs. */ public int available() throws IOException { return 0; }
close
close 方法,此处为空实现,由子类去实现。
/** * Closes this input stream and releases any system resources associated * with the stream. * * <p> The <code>close</code> method of <code>InputStream</code> does * nothing. * * @exception IOException if an I/O error occurs. */ public void close() throws IOException {}
mark/reset/markSupport
mark 定义一个方法,在输入流中标记当前位置,使用 reset 方法可以当前读流的位置重置到mark标记的位置。
readlimit 制定最大的重读数,相当于新建一个数组,将这段数据读入数组中,那么就可重复的读取这段数据,但是超过了数组大小,就无法重读这段数据了。这段理解有问题,只是说明意思,很多的类不支持这种。
/** * Marks the current position in this input stream. A subsequent call to * the <code>reset</code> method repositions this stream at the last marked * position so that subsequent reads re-read the same bytes. * * <p> The <code>readlimit</code> arguments tells this input stream to * allow that many bytes to be read before the mark position gets * invalidated. * * <p> The general contract of <code>mark</code> is that, if the method * <code>markSupported</code> returns <code>true</code>, the stream somehow * remembers all the bytes read after the call to <code>mark</code> and * stands ready to supply those same bytes again if and whenever the method * <code>reset</code> is called. However, the stream is not required to * remember any data at all if more than <code>readlimit</code> bytes are * read from the stream before <code>reset</code> is called. * * <p> Marking a closed stream should not have any effect on the stream. * * <p> The <code>mark</code> method of <code>InputStream</code> does * nothing. * * @param readlimit the maximum limit of bytes that can be read before * the mark position becomes invalid. * @see java.io.InputStream#reset() */ public synchronized void mark(int readlimit) {}
markSupport ,当前流是否支持标记
/** * Tests if this input stream supports the <code>mark</code> and * <code>reset</code> methods. Whether or not <code>mark</code> and * <code>reset</code> are supported is an invariant property of a * particular input stream instance. The <code>markSupported</code> method * of <code>InputStream</code> returns <code>false</code>. * * @return <code>true</code> if this stream instance supports the mark * and reset methods; <code>false</code> otherwise. * @see java.io.InputStream#mark(int) * @see java.io.InputStream#reset() */ public boolean markSupported() { return false; }
reset 方法:我有时候都认为markSupport、mark、reset这三个方法是为数组类的流准备的,比如StringBufferInputStream/ByteArrayInputStream准备的。
/** * Repositions this stream to the position at the time the * <code>mark</code> method was last called on this input stream. * * <p> The general contract of <code>reset</code> is: * * <ul> * <li> If the method <code>markSupported</code> returns * <code>true</code>, then: * * <ul><li> If the method <code>mark</code> has not been called since * the stream was created, or the number of bytes read from the stream * since <code>mark</code> was last called is larger than the argument * to <code>mark</code> at that last call, then an * <code>IOException</code> might be thrown. * * <li> If such an <code>IOException</code> is not thrown, then the * stream is reset to a state such that all the bytes read since the * most recent call to <code>mark</code> (or since the start of the * file, if <code>mark</code> has not been called) will be resupplied * to subsequent callers of the <code>read</code> method, followed by * any bytes that otherwise would have been the next input data as of * the time of the call to <code>reset</code>. </ul> * * <li> If the method <code>markSupported</code> returns * <code>false</code>, then: * * <ul><li> The call to <code>reset</code> may throw an * <code>IOException</code>. * * <li> If an <code>IOException</code> is not thrown, then the stream * is reset to a fixed state that depends on the particular type of the * input stream and how it was created. The bytes that will be supplied * to subsequent callers of the <code>read</code> method depend on the * particular type of the input stream. </ul></ul> * * <p>The method <code>reset</code> for class <code>InputStream</code> * does nothing except throw an <code>IOException</code>. * * @exception IOException if this stream has not been marked or if the * mark has been invalidated. * @see java.io.InputStream#mark(int) * @see java.io.IOException */ public synchronized void reset() throws IOException { throw new IOException("mark/reset not supported"); }
OutputStream
write抽象类
write():抽象函数,由具体类去实现。传入的为 int 类型,int为四个字节,低8位被使用,高24位被忽略
/** * Writes the specified byte to this output stream. The general * contract for <code>write</code> is that one byte is written * to the output stream. The byte to be written is the eight * low-order bits of the argument <code>b</code>. The 24 * high-order bits of <code>b</code> are ignored. * <p> * Subclasses of <code>OutputStream</code> must provide an * implementation for this method. * * @param b the <code>byte</code>. * @exception IOException if an I/O error occurs. In particular, * an <code>IOException</code> may be thrown if the * output stream has been closed. */ public abstract void write(int b) throws IOException;
write方法重载
write,将字节数组的 off 位置开始,写入 len 个长度
/** * Writes <code>len</code> bytes from the specified byte array * starting at offset <code>off</code> to this output stream. * The general contract for <code>write(b, off, len)</code> is that * some of the bytes in the array <code>b</code> are written to the * output stream in order; element <code>b[off]</code> is the first * byte written and <code>b[off+len-1]</code> is the last byte written * by this operation. * <p> * The <code>write</code> method of <code>OutputStream</code> calls * the write method of one argument on each of the bytes to be * written out. Subclasses are encouraged to override this method and * provide a more efficient implementation. * <p> * If <code>b</code> is <code>null</code>, a * <code>NullPointerException</code> is thrown. * <p> * If <code>off</code> is negative, or <code>len</code> is negative, or * <code>off+len</code> is greater than the length of the array * <code>b</code>, then an <tt>IndexOutOfBoundsException</tt> is thrown. * * @param b the data. * @param off the start offset in the data. * @param len the number of bytes to write. * @exception IOException if an I/O error occurs. In particular, * an <code>IOException</code> is thrown if the output * stream is closed. */ 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]); } }
write,将数组内元素全部写入流中
/** * Writes <code>b.length</code> bytes from the specified byte array * to this output stream. The general contract for <code>write(b)</code> * is that it should have exactly the same effect as the call * <code>write(b, 0, b.length)</code>. * * @param b the data. * @exception IOException if an I/O error occurs. * @see java.io.OutputStream#write(byte[], int, int) */ public void write(byte b[]) throws IOException { write(b, 0, b.length); }
flush
flush:如果是数组类的输出流,则强制数组内的字节写出。如果是文件流这种的,该方法仅仅保证之前写出的流传递给操作系统去写,却不能保证这些数据被立即写到文件中。
/** * Flushes this output stream and forces any buffered output bytes * to be written out. The general contract of <code>flush</code> is * that calling it is an indication that, if any bytes previously * written have been buffered by the implementation of the output * stream, such bytes should immediately be written to their * intended destination. * <p> * If the intended destination of this stream is an abstraction provided by * the underlying operating system, for example a file, then flushing the * stream guarantees only that bytes previously written to the stream are * passed to the operating system for writing; it does not guarantee that * they are actually written to a physical device such as a disk drive. * <p> * The <code>flush</code> method of <code>OutputStream</code> does nothing. * * @exception IOException if an I/O error occurs. */ public void flush() throws IOException { }
close
close,关闭输出流
/** * Closes this output stream and releases any system resources * associated with this stream. The general contract of <code>close</code> * is that it closes the output stream. A closed stream cannot perform * output operations and cannot be reopened. * <p> * The <code>close</code> method of <code>OutputStream</code> does nothing. * * @exception IOException if an I/O error occurs. */ public void close() throws IOException { }