OutputStream 类实现关系

本贴最后更新于 1107 天前,其中的信息可能已经物是人非

本文主要从 JDK 源码角度分析 OutputStream。 @Eason Gao

OutputStream 类实现关系

OutputStream 抽象类

OutputStream 类

 public abstract void write(int b)  // 写入一个字节,可以看到这里的参数是一个 int 类型,对应上面的读方法,int 类型的 32 位,只有低 8 位才写入,高 24 位将舍弃。    public void write(byte b[])  // 将数组中的所有字节写入,和上面对应的 read() 方法类似,实际调用的也是下面的方法。    public void write(byte b[], int off, int len)  // 将 byte 数组从 off 位置开始,len 长度的字节写入    public void flush()  // 强制刷新,将缓冲中的数据写入    public void close()  // 关闭输出流,流被关闭后就不能再输出数据了

源码实现

FilterOutputStream

 /**   * This class is the superclass of all classes that filter output   * streams. These streams sit on top of an already existing output   * stream (the <i>underlying</i> output stream) which it uses as its   * basic sink of data, but possibly transforming the data along the   * way or providing additional functionality.   * <p>   * The class <code>FilterOutputStream</code> itself simply overrides   * all methods of <code>OutputStream</code> with versions that pass   * all requests to the underlying output stream. Subclasses of   * <code>FilterOutputStream</code> may further override some of these   * methods as well as provide additional methods and fields.   *   * @author Jonathan Payne   * @since   JDK1.0   */  public  class FilterOutputStream extends OutputStream {      /**       * The underlying output stream to be filtered.       */      protected OutputStream out;        /**       * Creates an output stream filter built on top of the specified       * underlying output stream.       *       * @param   out   the underlying output stream to be assigned to       *               the field <tt>this.out</tt> for later use, or       *               <code>null</code> if this instance is to be       *               created without an underlying stream.       */      public FilterOutputStream(OutputStream out) {          this.out = out;     }        /**       * Writes the specified <code>byte</code> to this output stream.       * <p>       * The <code>write</code> method of <code>FilterOutputStream</code>       * calls the <code>write</code> method of its underlying output stream,       * that is, it performs <tt>out.write(b)</tt>.       * <p>       * Implements the abstract <tt>write</tt> method of <tt>OutputStream</tt>.       *       * @param     b   the <code>byte</code>.       * @exception IOException if an I/O error occurs.       */      public void write(int b) throws IOException {          out.write(b);     }        /**       * Writes <code>b.length</code> bytes to this output stream.       * <p>       * The <code>write</code> method of <code>FilterOutputStream</code>       * calls its <code>write</code> method of three arguments with the       * arguments <code>b</code>, <code>0</code>, and       * <code>b.length</code>.       * <p>       * Note that this method does not call the one-argument       * <code>write</code> method of its underlying stream with the single       * argument <code>b</code>.       *       * @param     b   the data to be written.       * @exception IOException if an I/O error occurs.       * @see       java.io.FilterOutputStream#write(byte[], int, int)       */      public void write(byte b[]) throws IOException {          write(b, 0, b.length);     }        /**       * Writes <code>len</code> bytes from the specified       * <code>byte</code> array starting at offset <code>off</code> to       * this output stream.       * <p>       * The <code>write</code> method of <code>FilterOutputStream</code>       * calls the <code>write</code> method of one argument on each       * <code>byte</code> to output.       * <p>       * Note that this method does not call the <code>write</code> method       * of its underlying input stream with the same arguments. Subclasses       * of <code>FilterOutputStream</code> should provide a more efficient       * implementation of this method.       *       * @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.       * @see       java.io.FilterOutputStream#write(int)       */      public void write(byte b[], int off, int len) throws IOException {          if ((off | len | (b.length - (len + off)) | (off + len)) < 0)              throw new IndexOutOfBoundsException();            for (int i = 0 ; i < len ; i++) {              write(b[off + i]);         }     }        /**       * Flushes this output stream and forces any buffered output bytes       * to be written out to the stream.       * <p>       * The <code>flush</code> method of <code>FilterOutputStream</code>       * calls the <code>flush</code> method of its underlying output stream.       *       * @exception IOException if an I/O error occurs.       * @see       java.io.FilterOutputStream#out       */      public void flush() throws IOException {          out.flush();     }        /**       * Closes this output stream and releases any system resources       * associated with the stream.       * <p>       * The <code>close</code> method of <code>FilterOutputStream</code>       * calls its <code>flush</code> method, and then calls the       * <code>close</code> method of its underlying output stream.       *       * @exception IOException if an I/O error occurs.       * @see       java.io.FilterOutputStream#flush()       * @see       java.io.FilterOutputStream#out       */      @SuppressWarnings("try")      public void close() throws IOException {          try (OutputStream ostream = out) {              flush();         }     }  }

ByteArrayOutputStream

 /**   * This class implements an output stream in which the data is   * written into a byte array. The buffer automatically grows as data   * is written to it.   * The data can be retrieved using <code>toByteArray()</code> and   * <code>toString()</code>.   * <p>   * Closing a <tt>ByteArrayOutputStream</tt> has no effect. The methods in   * this class can be called after the stream has been closed without   * generating an <tt>IOException</tt>.   *   * @author Arthur van Hoff   * @since   JDK1.0   */    public class ByteArrayOutputStream extends OutputStream {        /**       * The buffer where data is stored.       */      protected byte buf[];        /**       * The number of valid bytes in the buffer.       */      protected int count;        /**       * Creates a new byte array output stream. The buffer capacity is       * initially 32 bytes, though its size increases if necessary.       */      public ByteArrayOutputStream() {          this(32);     }        /**       * Creates a new byte array output stream, with a buffer capacity of       * the specified size, in bytes.       *       * @param   size   the initial size.       * @exception IllegalArgumentException if size is negative.       */      public ByteArrayOutputStream(int size) {          if (size < 0) {              throw new IllegalArgumentException("Negative initial size: "                                                 + size);         }          buf = new byte[size];     }        /**       * Increases the capacity if necessary to ensure that it can hold       * at least the number of elements specified by the minimum       * capacity argument.       *       * @param minCapacity the desired minimum capacity       * @throws OutOfMemoryError if {@code minCapacity < 0}. This is       * interpreted as a request for the unsatisfiably large capacity       * {@code (long) Integer.MAX_VALUE + (minCapacity - Integer.MAX_VALUE)}.       */      private void ensureCapacity(int minCapacity) {          // overflow-conscious code          if (minCapacity - buf.length > 0)              grow(minCapacity);     }        /**       * The maximum size of array to allocate.       * Some VMs reserve some header words in an array.       * Attempts to allocate larger arrays may result in       * OutOfMemoryError: Requested array size exceeds VM limit       */      private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;        /**       * Increases the capacity to ensure that it can hold at least the       * number of elements specified by the minimum capacity argument.       *       * @param minCapacity the desired minimum capacity       */      private void grow(int minCapacity) {          // overflow-conscious code          int oldCapacity = buf.length;          int newCapacity = oldCapacity << 1;          if (newCapacity - minCapacity < 0)              newCapacity = minCapacity;          if (newCapacity - MAX_ARRAY_SIZE > 0)              newCapacity = hugeCapacity(minCapacity);          buf = Arrays.copyOf(buf, newCapacity);     }        private static int hugeCapacity(int minCapacity) {          if (minCapacity < 0) // overflow              throw new OutOfMemoryError();          return (minCapacity > MAX_ARRAY_SIZE) ?              Integer.MAX_VALUE :              MAX_ARRAY_SIZE;     }        /**       * Writes the specified byte to this byte array output stream.       *       * @param   b   the byte to be written.       */      public synchronized void write(int b) {          ensureCapacity(count + 1);          buf[count] = (byte) b;          count += 1;     }        /**       * Writes <code>len</code> bytes from the specified byte array       * starting at offset <code>off</code> to this byte array output stream.       *       * @param   b     the data.       * @param   off   the start offset in the data.       * @param   len   the number of bytes to write.       */      public synchronized void write(byte b[], int off, int len) {          if ((off < 0) || (off > b.length) || (len < 0) ||             ((off + len) - b.length > 0)) {              throw new IndexOutOfBoundsException();         }          ensureCapacity(count + len);          System.arraycopy(b, off, buf, count, len);          count += len;     }        /**       * Writes the complete contents of this byte array output stream to       * the specified output stream argument, as if by calling the output       * stream's write method using <code>out.write(buf, 0, count)</code>.       *       * @param     out   the output stream to which to write the data.       * @exception IOException if an I/O error occurs.       */      public synchronized void writeTo(OutputStream out) throws IOException {          out.write(buf, 0, count);     }        /**       * Resets the <code>count</code> field of this byte array output       * stream to zero, so that all currently accumulated output in the       * output stream is discarded. The output stream can be used again,       * reusing the already allocated buffer space.       *       * @see     java.io.ByteArrayInputStream#count       */      public synchronized void reset() {          count = 0;     }        /**       * Creates a newly allocated byte array. Its size is the current       * size of this output stream and the valid contents of the buffer       * have been copied into it.       *       * @return the current contents of this output stream, as a byte array.       * @see     java.io.ByteArrayOutputStream#size()       */      public synchronized byte toByteArray()[] {          return Arrays.copyOf(buf, count);     }        /**       * Returns the current size of the buffer.       *       * @return the value of the <code>count</code> field, which is the number       *         of valid bytes in this output stream.       * @see     java.io.ByteArrayOutputStream#count       */      public synchronized int size() {          return count;     }        /**       * Converts the buffer's contents into a string decoding bytes using the       * platform's default character set. The length of the new <tt>String</tt>       * is a function of the character set, and hence may not be equal to the       * size of the buffer.       *       * <p> This method always replaces malformed-input and unmappable-character       * sequences with the default replacement string for the platform's       * default character set. The {@linkplain java.nio.charset.CharsetDecoder}       * class should be used when more control over the decoding process is       * required.       *       * @return String decoded from the buffer's contents.       * @since JDK1.1       */      public synchronized String toString() {          return new String(buf, 0, count);     }        /**       * Converts the buffer's contents into a string by decoding the bytes using       * the named {@link java.nio.charset.Charset charset}. The length of the new       * <tt>String</tt> is a function of the charset, and hence may not be equal       * to the length of the byte array.       *       * <p> This method always replaces malformed-input and unmappable-character       * sequences with this charset's default replacement string. The {@link       * java.nio.charset.CharsetDecoder} class should be used when more control       * over the decoding process is required.       *       * @param     charsetName the name of a supported       *             {@link java.nio.charset.Charset charset}       * @return     String decoded from the buffer's contents.       * @exception UnsupportedEncodingException       *             If the named charset is not supported       * @since     JDK1.1       */      public synchronized String toString(String charsetName)          throws UnsupportedEncodingException     {          return new String(buf, 0, count, charsetName);     }        /**       * Creates a newly allocated string. Its size is the current size of       * the output stream and the valid contents of the buffer have been       * copied into it. Each character <i>c</i> in the resulting string is       * constructed from the corresponding element <i>b</i> in the byte       * array such that:       * <blockquote><pre>       *     c == (char)(((hibyte & 0xff) << 8) | (b & 0xff))       * </pre></blockquote>       *       * @deprecated This method does not properly convert bytes into characters.       * As of JDK 1.1, the preferred way to do this is via the       * <code>toString(String enc)</code> method, which takes an encoding-name       * argument, or the <code>toString()</code> method, which uses the       * platform's default character encoding.       *       * @param     hibyte   the high byte of each resulting Unicode character.       * @return     the current contents of the output stream, as a string.       * @see       java.io.ByteArrayOutputStream#size()       * @see       java.io.ByteArrayOutputStream#toString(String)       * @see       java.io.ByteArrayOutputStream#toString()       */      @Deprecated      public synchronized String toString(int hibyte) {          return new String(buf, hibyte, 0, count);     }        /**       * Closing a <tt>ByteArrayOutputStream</tt> has no effect. The methods in       * this class can be called after the stream has been closed without       * generating an <tt>IOException</tt>.       */      public void close() throws IOException {     }    }

BufferedOutputStream

 /**   * The class implements a buffered output stream. By setting up such   * an output stream, an application can write bytes to the underlying   * output stream without necessarily causing a call to the underlying   * system for each byte written.   *   * @author Arthur van Hoff   * @since   JDK1.0   */  public  class BufferedOutputStream extends FilterOutputStream {      /**       * The internal buffer where data is stored.       */      protected byte buf[];        /**       * The number of valid bytes in the buffer. This value is always       * in the range <tt>0</tt> through <tt>buf.length</tt>; elements       * <tt>buf[0]</tt> through <tt>buf[count-1]</tt> contain valid       * byte data.       */      protected int count;        /**       * Creates a new buffered output stream to write data to the       * specified underlying output stream.       *       * @param   out   the underlying output stream.       */      public BufferedOutputStream(OutputStream out) {          this(out, 8192);     }        /**       * Creates a new buffered output stream to write data to the       * specified underlying output stream with the specified buffer       * size.       *       * @param   out   the underlying output stream.       * @param   size   the buffer size.       * @exception IllegalArgumentException if size <= 0.       */      public BufferedOutputStream(OutputStream out, int size) {          super(out);          if (size <= 0) {              throw new IllegalArgumentException("Buffer size <= 0");         }          buf = new byte[size];     }        /** Flush the internal buffer */      private void flushBuffer() throws IOException {          if (count > 0) {              out.write(buf, 0, count);              count = 0;         }     }        /**       * Writes the specified byte to this buffered output stream.       *       * @param     b   the byte to be written.       * @exception IOException if an I/O error occurs.       */      public synchronized void write(int b) throws IOException {          if (count >= buf.length) {              flushBuffer();         }          buf[count++] = (byte)b;     }        /**       * Writes <code>len</code> bytes from the specified byte array       * starting at offset <code>off</code> to this buffered output stream.       *       * <p> Ordinarily this method stores bytes from the given array into this       * stream's buffer, flushing the buffer to the underlying output stream as       * needed. If the requested length is at least as large as this stream's       * buffer, however, then this method will flush the buffer and write the       * bytes directly to the underlying output stream. Thus redundant       * <code>BufferedOutputStream</code>s will not copy data unnecessarily.       *       * @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.       */      public synchronized void write(byte b[], int off, int len) throws IOException {          if (len >= buf.length) {              /* If the request length exceeds the size of the output buffer,                 flush the output buffer and then write the data directly.                 In this way buffered streams will cascade harmlessly. */              flushBuffer();              out.write(b, off, len);              return;         }          if (len > buf.length - count) {              flushBuffer();         }          System.arraycopy(b, off, buf, count, len);          count += len;     }        /**       * Flushes this buffered output stream. This forces any buffered       * output bytes to be written out to the underlying output stream.       *       * @exception IOException if an I/O error occurs.       * @see       java.io.FilterOutputStream#out       */      public synchronized void flush() throws IOException {          flushBuffer();          out.flush();     }  }

PipedOutputStream

 /**   * A piped output stream can be connected to a piped input stream   * to create a communications pipe. The piped output stream is the   * sending end of the pipe. Typically, data is written to a   * <code>PipedOutputStream</code> object by one thread and data is   * read from the connected <code>PipedInputStream</code> by some   * other thread. Attempting to use both objects from a single thread   * is not recommended as it may deadlock the thread.   * The pipe is said to be <a name=BROKEN> <i>broken</i> </a> if a   * thread that was reading data bytes from the connected piped input   * stream is no longer alive.   *   * @author James Gosling   * @see     java.io.PipedInputStream   * @since   JDK1.0   */  public  class PipedOutputStream extends OutputStream {            /* REMIND: identification of the read and write sides needs to be             more sophisticated. Either using thread groups (but what about             pipes within a thread?) or using finalization (but it may be a             long time until the next GC). */      private PipedInputStream sink;        /**       * Creates a piped output stream connected to the specified piped       * input stream. Data bytes written to this stream will then be       * available as input from <code>snk</code>.       *       * @param     snk   The piped input stream to connect to.       * @exception IOException if an I/O error occurs.       */      public PipedOutputStream(PipedInputStream snk)  throws IOException {          connect(snk);     }        /**       * Creates a piped output stream that is not yet connected to a       * piped input stream. It must be connected to a piped input stream,       * either by the receiver or the sender, before being used.       *       * @see     java.io.PipedInputStream#connect(java.io.PipedOutputStream)       * @see     java.io.PipedOutputStream#connect(java.io.PipedInputStream)       */      public PipedOutputStream() {     }        /**       * Connects this piped output stream to a receiver. If this object       * is already connected to some other piped input stream, an       * <code>IOException</code> is thrown.       * <p>       * If <code>snk</code> is an unconnected piped input stream and       * <code>src</code> is an unconnected piped output stream, they may       * be connected by either the call:       * <blockquote><pre>       * src.connect(snk)</pre></blockquote>       * or the call:       * <blockquote><pre>       * snk.connect(src)</pre></blockquote>       * The two calls have the same effect.       *       * @param     snk   the piped input stream to connect to.       * @exception IOException if an I/O error occurs.       */      public synchronized void connect(PipedInputStream snk) throws IOException {          if (snk == null) {              throw new NullPointerException();         } else if (sink != null || snk.connected) {              throw new IOException("Already connected");         }          sink = snk;          snk.in = -1;          snk.out = 0;          snk.connected = true;     }        /**       * Writes the specified <code>byte</code> to the piped output stream.       * <p>       * Implements the <code>write</code> method of <code>OutputStream</code>.       *       * @param     b   the <code>byte</code> to be written.       * @exception IOException if the pipe is <a href=#BROKEN> broken</a>,       *         {@link #connect(java.io.PipedInputStream) unconnected},       *         closed, or if an I/O error occurs.       */      public void write(int b)  throws IOException {          if (sink == null) {              throw new IOException("Pipe not connected");         }          sink.receive(b);     }        /**       * Writes <code>len</code> bytes from the specified byte array       * starting at offset <code>off</code> to this piped output stream.       * This method blocks until all the bytes are written to the output       * stream.       *       * @param     b     the data.       * @param     off   the start offset in the data.       * @param     len   the number of bytes to write.       * @exception IOException if the pipe is <a href=#BROKEN> broken</a>,       *         {@link #connect(java.io.PipedInputStream) unconnected},       *         closed, or if an I/O error occurs.       */      public void write(byte b[], int off, int len) throws IOException {          if (sink == null) {              throw new IOException("Pipe not connected");         } else 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;         }          sink.receive(b, off, len);     }        /**       * Flushes this output stream and forces any buffered output bytes       * to be written out.       * This will notify any readers that bytes are waiting in the pipe.       *       * @exception IOException if an I/O error occurs.       */      public synchronized void flush() throws IOException {          if (sink != null) {              synchronized (sink) {                  sink.notifyAll();             }         }     }        /**       * Closes this piped output stream and releases any system resources       * associated with this stream. This stream may no longer be used for       * writing bytes.       *       * @exception IOException if an I/O error occurs.       */      public void close()  throws IOException {          if (sink != null) {              sink.receivedLast();         }     }  }
  • Java

    Java 是一种可以撰写跨平台应用软件的面向对象的程序设计语言,是由 Sun Microsystems 公司于 1995 年 5 月推出的。Java 技术具有卓越的通用性、高效性、平台移植性和安全性。

    3197 引用 • 8215 回帖

相关帖子

欢迎来到这里!

我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。

注册 关于
请输入回帖内容 ...