zoukankan      html  css  js  c++  java
  • java io

    之前的博客总是不是从书中摘录就是从别人的文章中copy点,加点自己轻微的思考,就认为,哇,我又完成一篇。现在要尝试,尽量(有些类啊API啊还是要copy滴)不拷贝任何文章书籍,自己写!

      java io在编程中或多或少都遇到,比如读取文件了,比如接口返回的是一堆流信息。那么针对这些流怎么处理呢?这时候就是io上场的时候了。jdk1.4之后加入了新的io叫nio,之前我总是不明白,既然都有了更好的nio了,那为何还不淘汰掉旧io呢?随着书籍和文章的阅读,代码的查阅,对这个问题终于知道了一些。两者的适用场景不同。正如他们的实现方式不一样。一个阻塞,一个非阻塞。

      首先呢,我先来记录下近期对io的理解。

      网上搜索关于java io总会出现一大堆的类的继承图,看得人昏昏欲睡,一点学习的念头都没,那么多类,那么多继承关系。其实呢这么多累的关系之所以看起来那么复杂,是因为没有明白一个设计模式,叫做装饰器模式。接口InputStream不用说,定义功能的。他下面的继承类中只需要关注这么几个(我个人觉得)ByteArrayInputStream(比特数组流),StringInputStream(字符串流),PipedInputStream(管道流),FileInputStream(文件流),DataInputStream,FilterInputStream(装饰器)。根据他们的名字,差不多就能知道他们的适用场景。具体的每个流的demo要不要贴,后面再思考吧。先讲讲FilterInputStream,FilterInputStream就是传说中的装饰器,下面让我们来个他的源码

      

    /*
     * Copyright (c) 1994, 2010, Oracle and/or its affiliates. All rights reserved.
     * ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
     *
     *
     *
     *
     *
     *
     *
     *
     *
     *
     *
     *
     *
     *
     *
     *
     *
     *
     *
     *
     */
    
    package java.io;
    
    /**
     * A <code>FilterInputStream</code> contains
     * some other input stream, which it uses as
     * its  basic source of data, possibly transforming
     * the data along the way or providing  additional
     * functionality. The class <code>FilterInputStream</code>
     * itself simply overrides all  methods of
     * <code>InputStream</code> with versions that
     * pass all requests to the contained  input
     * stream. Subclasses of <code>FilterInputStream</code>
     * may further override some of  these methods
     * and may also provide additional methods
     * and fields.
     *
     * @author  Jonathan Payne
     * @since   JDK1.0
     */
    public
    class FilterInputStream extends InputStream {
        /**
         * The input stream to be filtered.
         */
        protected volatile InputStream in;
    
        /**
         * Creates a <code>FilterInputStream</code>
         * by assigning the  argument <code>in</code>
         * to the field <code>this.in</code> so as
         * to remember it for later use.
         *
         * @param   in   the underlying input stream, or <code>null</code> if
         *          this instance is to be created without an underlying stream.
         */
        protected FilterInputStream(InputStream in) {
            this.in = in;
        }
    
        /**
         * Reads the next byte of data from this 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>
         * This method
         * simply performs <code>in.read()</code> and returns the result.
         *
         * @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.
         * @see        java.io.FilterInputStream#in
         */
        public int read() throws IOException {
            return in.read();
        }
    
        /**
         * Reads up to <code>byte.length</code> bytes of data from this
         * input stream into an array of bytes. This method blocks until some
         * input is available.
         * <p>
         * This method simply performs the call
         * <code>read(b, 0, b.length)</code> and returns
         * the  result. It is important that it does
         * <i>not</i> do <code>in.read(b)</code> instead;
         * certain subclasses of  <code>FilterInputStream</code>
         * depend on the implementation strategy actually
         * used.
         *
         * @param      b   the buffer into which the data is read.
         * @return     the total number of bytes read into the buffer, or
         *             <code>-1</code> if there is no more data because the end of
         *             the stream has been reached.
         * @exception  IOException  if an I/O error occurs.
         * @see        java.io.FilterInputStream#read(byte[], int, int)
         */
        public int read(byte b[]) throws IOException {
            return read(b, 0, b.length);
        }
    
        /**
         * Reads up to <code>len</code> bytes of data from this input stream
         * into an array of bytes. If <code>len</code> is not zero, the method
         * blocks until some input is available; otherwise, no
         * bytes are read and <code>0</code> is returned.
         * <p>
         * This method simply performs <code>in.read(b, off, len)</code>
         * and returns the result.
         *
         * @param      b     the buffer into which the data is read.
         * @param      off   the start offset in the destination array <code>b</code>
         * @param      len   the maximum number of bytes read.
         * @return     the total number of bytes read into the buffer, or
         *             <code>-1</code> if there is no more data because the end of
         *             the stream has been reached.
         * @exception  NullPointerException If <code>b</code> is <code>null</code>.
         * @exception  IndexOutOfBoundsException If <code>off</code> is negative,
         * <code>len</code> is negative, or <code>len</code> is greater than
         * <code>b.length - off</code>
         * @exception  IOException  if an I/O error occurs.
         * @see        java.io.FilterInputStream#in
         */
        public int read(byte b[], int off, int len) throws IOException {
            return in.read(b, off, len);
        }
    
        /**
         * Skips over and discards <code>n</code> bytes of data from the
         * input stream. The <code>skip</code> method may, for a variety of
         * reasons, end up skipping over some smaller number of bytes,
         * possibly <code>0</code>. The actual number of bytes skipped is
         * returned.
         * <p>
         * This method simply performs <code>in.skip(n)</code>.
         *
         * @param      n   the number of bytes to be skipped.
         * @return     the actual number of bytes skipped.
         * @exception  IOException  if the stream does not support seek,
         *                          or if some other I/O error occurs.
         */
        public long skip(long n) throws IOException {
            return in.skip(n);
        }
    
        /**
         * Returns an estimate of the number of bytes that can be read (or
         * skipped over) from this input stream without blocking by the next
         * caller of a method for this input stream. The next caller 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>
         * This method returns the result of {@link #in in}.available().
         *
         * @return     an estimate of the number of bytes that can be read (or skipped
         *             over) from this input stream without blocking.
         * @exception  IOException  if an I/O error occurs.
         */
        public int available() throws IOException {
            return in.available();
        }
    
        /**
         * Closes this input stream and releases any system resources
         * associated with the stream.
         * This
         * method simply performs <code>in.close()</code>.
         *
         * @exception  IOException  if an I/O error occurs.
         * @see        java.io.FilterInputStream#in
         */
        public void close() throws IOException {
            in.close();
        }
    
        /**
         * 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> argument tells this input stream to
         * allow that many bytes to be read before the mark position gets
         * invalidated.
         * <p>
         * This method simply performs <code>in.mark(readlimit)</code>.
         *
         * @param   readlimit   the maximum limit of bytes that can be read before
         *                      the mark position becomes invalid.
         * @see     java.io.FilterInputStream#in
         * @see     java.io.FilterInputStream#reset()
         */
        public synchronized void mark(int readlimit) {
            in.mark(readlimit);
        }
    
        /**
         * Repositions this stream to the position at the time the
         * <code>mark</code> method was last called on this input stream.
         * <p>
         * This method
         * simply performs <code>in.reset()</code>.
         * <p>
         * Stream marks are intended to be used in
         * situations where you need to read ahead a little to see what's in
         * the stream. Often this is most easily done by invoking some
         * general parser. If the stream is of the type handled by the
         * parse, it just chugs along happily. If the stream is not of
         * that type, the parser should toss an exception when it fails.
         * If this happens within readlimit bytes, it allows the outer
         * code to reset the stream and try another parser.
         *
         * @exception  IOException  if the stream has not been marked or if the
         *               mark has been invalidated.
         * @see        java.io.FilterInputStream#in
         * @see        java.io.FilterInputStream#mark(int)
         */
        public synchronized void reset() throws IOException {
            in.reset();
        }
    
        /**
         * Tests if this input stream supports the <code>mark</code>
         * and <code>reset</code> methods.
         * This method
         * simply performs <code>in.markSupported()</code>.
         *
         * @return  <code>true</code> if this stream type supports the
         *          <code>mark</code> and <code>reset</code> method;
         *          <code>false</code> otherwise.
         * @see     java.io.FilterInputStream#in
         * @see     java.io.InputStream#mark(int)
         * @see     java.io.InputStream#reset()
         */
        public boolean markSupported() {
            return in.markSupported();
        }
    }
    View Code

      仔细观察,你会发现,这家伙在开始就有这么个定义

       /**
         * The input stream to be filtered.
         */
        protected volatile InputStream in;

    这是啥?我的第一感觉就是。这不是策略模式的形状吗?

    这里的FilterInputStream其实什么都不做的,真正干活的是传给他的in,而他的子类就是利用那些传进来的in做一些功能处理。比如我最常用的BufferedInputStream就是增加了缓存这一步骤,从而实现效率,不过看BufferedInputStream的源码,你会发现,真正读取流信息的动作还是传给他的in!,下面上BufferedInputStream的代码。

    /*
     * Copyright (c) 1994, 2010, Oracle and/or its affiliates. All rights reserved.
     * ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
     *
     *
     *
     *
     *
     *
     *
     *
     *
     *
     *
     *
     *
     *
     *
     *
     *
     *
     *
     *
     */
    
    package java.io;
    import java.util.concurrent.atomic.AtomicReferenceFieldUpdater;
    
    /**
     * A <code>BufferedInputStream</code> adds
     * functionality to another input stream-namely,
     * the ability to buffer the input and to
     * support the <code>mark</code> and <code>reset</code>
     * methods. When  the <code>BufferedInputStream</code>
     * is created, an internal buffer array is
     * created. As bytes  from the stream are read
     * or skipped, the internal buffer is refilled
     * as necessary  from the contained input stream,
     * many bytes at a time. The <code>mark</code>
     * operation  remembers a point in the input
     * stream and the <code>reset</code> operation
     * causes all the  bytes read since the most
     * recent <code>mark</code> operation to be
     * reread before new bytes are  taken from
     * the contained input stream.
     *
     * @author  Arthur van Hoff
     * @since   JDK1.0
     */
    public
    class BufferedInputStream extends FilterInputStream {
    
        private static int defaultBufferSize = 8192;
    
        /**
         * The internal buffer array where the data is stored. When necessary,
         * it may be replaced by another array of
         * a different size.
         */
        protected volatile byte buf[];
    
        /**
         * Atomic updater to provide compareAndSet for buf. This is
         * necessary because closes can be asynchronous. We use nullness
         * of buf[] as primary indicator that this stream is closed. (The
         * "in" field is also nulled out on close.)
         */
        private static final
            AtomicReferenceFieldUpdater<BufferedInputStream, byte[]> bufUpdater =
            AtomicReferenceFieldUpdater.newUpdater
            (BufferedInputStream.class,  byte[].class, "buf");
    
        /**
         * The index one greater than the index of the last valid byte in
         * the buffer.
         * This value is always
         * in the range <code>0</code> through <code>buf.length</code>;
         * elements <code>buf[0]</code>  through <code>buf[count-1]
         * </code>contain buffered input data obtained
         * from the underlying  input stream.
         */
        protected int count;
    
        /**
         * The current position in the buffer. This is the index of the next
         * character to be read from the <code>buf</code> array.
         * <p>
         * This value is always in the range <code>0</code>
         * through <code>count</code>. If it is less
         * than <code>count</code>, then  <code>buf[pos]</code>
         * is the next byte to be supplied as input;
         * if it is equal to <code>count</code>, then
         * the  next <code>read</code> or <code>skip</code>
         * operation will require more bytes to be
         * read from the contained  input stream.
         *
         * @see     java.io.BufferedInputStream#buf
         */
        protected int pos;
    
        /**
         * The value of the <code>pos</code> field at the time the last
         * <code>mark</code> method was called.
         * <p>
         * This value is always
         * in the range <code>-1</code> through <code>pos</code>.
         * If there is no marked position in  the input
         * stream, this field is <code>-1</code>. If
         * there is a marked position in the input
         * stream,  then <code>buf[markpos]</code>
         * is the first byte to be supplied as input
         * after a <code>reset</code> operation. If
         * <code>markpos</code> is not <code>-1</code>,
         * then all bytes from positions <code>buf[markpos]</code>
         * through  <code>buf[pos-1]</code> must remain
         * in the buffer array (though they may be
         * moved to  another place in the buffer array,
         * with suitable adjustments to the values
         * of <code>count</code>,  <code>pos</code>,
         * and <code>markpos</code>); they may not
         * be discarded unless and until the difference
         * between <code>pos</code> and <code>markpos</code>
         * exceeds <code>marklimit</code>.
         *
         * @see     java.io.BufferedInputStream#mark(int)
         * @see     java.io.BufferedInputStream#pos
         */
        protected int markpos = -1;
    
        /**
         * The maximum read ahead allowed after a call to the
         * <code>mark</code> method before subsequent calls to the
         * <code>reset</code> method fail.
         * Whenever the difference between <code>pos</code>
         * and <code>markpos</code> exceeds <code>marklimit</code>,
         * then the  mark may be dropped by setting
         * <code>markpos</code> to <code>-1</code>.
         *
         * @see     java.io.BufferedInputStream#mark(int)
         * @see     java.io.BufferedInputStream#reset()
         */
        protected int marklimit;
    
        /**
         * Check to make sure that underlying input stream has not been
         * nulled out due to close; if not return it;
         */
        private InputStream getInIfOpen() throws IOException {
            InputStream input = in;
            if (input == null)
                throw new IOException("Stream closed");
            return input;
        }
    
        /**
         * Check to make sure that buffer has not been nulled out due to
         * close; if not return it;
         */
        private byte[] getBufIfOpen() throws IOException {
            byte[] buffer = buf;
            if (buffer == null)
                throw new IOException("Stream closed");
            return buffer;
        }
    
        /**
         * Creates a <code>BufferedInputStream</code>
         * and saves its  argument, the input stream
         * <code>in</code>, for later use. An internal
         * buffer array is created and  stored in <code>buf</code>.
         *
         * @param   in   the underlying input stream.
         */
        public BufferedInputStream(InputStream in) {
            this(in, defaultBufferSize);
        }
    
        /**
         * Creates a <code>BufferedInputStream</code>
         * with the specified buffer size,
         * and saves its  argument, the input stream
         * <code>in</code>, for later use.  An internal
         * buffer array of length  <code>size</code>
         * is created and stored in <code>buf</code>.
         *
         * @param   in     the underlying input stream.
         * @param   size   the buffer size.
         * @exception IllegalArgumentException if size <= 0.
         */
        public BufferedInputStream(InputStream in, int size) {
            super(in);
            if (size <= 0) {
                throw new IllegalArgumentException("Buffer size <= 0");
            }
            buf = new byte[size];
        }
    
        /**
         * Fills the buffer with more data, taking into account
         * shuffling and other tricks for dealing with marks.
         * Assumes that it is being called by a synchronized method.
         * This method also assumes that all data has already been read in,
         * hence pos > count.
         */
        private void fill() throws IOException {
            byte[] buffer = getBufIfOpen();
            if (markpos < 0)
                pos = 0;            /* no mark: throw away the buffer */
            else if (pos >= buffer.length)  /* no room left in buffer */
                if (markpos > 0) {  /* can throw away early part of the buffer */
                    int sz = pos - markpos;
                    System.arraycopy(buffer, markpos, buffer, 0, sz);
                    pos = sz;
                    markpos = 0;
                } else if (buffer.length >= marklimit) {
                    markpos = -1;   /* buffer got too big, invalidate mark */
                    pos = 0;        /* drop buffer contents */
                } else {            /* grow buffer */
                    int nsz = pos * 2;
                    if (nsz > marklimit)
                        nsz = marklimit;
                    byte nbuf[] = new byte[nsz];
                    System.arraycopy(buffer, 0, nbuf, 0, pos);
                    if (!bufUpdater.compareAndSet(this, buffer, nbuf)) {
                        // Can't replace buf if there was an async close.
                        // Note: This would need to be changed if fill()
                        // is ever made accessible to multiple threads.
                        // But for now, the only way CAS can fail is via close.
                        // assert buf == null;
                        throw new IOException("Stream closed");
                    }
                    buffer = nbuf;
                }
            count = pos;
            int n = getInIfOpen().read(buffer, pos, buffer.length - pos);
            if (n > 0)
                count = n + pos;
        }
    
        /**
         * See
         * the general contract of the <code>read</code>
         * method of <code>InputStream</code>.
         *
         * @return     the next byte of data, or <code>-1</code> if the end of the
         *             stream is reached.
         * @exception  IOException  if this input stream has been closed by
         *                          invoking its {@link #close()} method,
         *                          or an I/O error occurs.
         * @see        java.io.FilterInputStream#in
         */
        public synchronized int read() throws IOException {
            if (pos >= count) {
                fill();
                if (pos >= count)
                    return -1;
            }
            return getBufIfOpen()[pos++] & 0xff;
        }
    
        /**
         * Read characters into a portion of an array, reading from the underlying
         * stream at most once if necessary.
         */
        private int read1(byte[] b, int off, int len) throws IOException {
            int avail = count - pos;
            if (avail <= 0) {
                /* If the requested length is at least as large as the buffer, and
                   if there is no mark/reset activity, do not bother to copy the
                   bytes into the local buffer.  In this way buffered streams will
                   cascade harmlessly. */
                if (len >= getBufIfOpen().length && markpos < 0) {
                    return getInIfOpen().read(b, off, len);
                }
                fill();
                avail = count - pos;
                if (avail <= 0) return -1;
            }
            int cnt = (avail < len) ? avail : len;
            System.arraycopy(getBufIfOpen(), pos, b, off, cnt);
            pos += cnt;
            return cnt;
        }
    
        /**
         * Reads bytes from this byte-input stream into the specified byte array,
         * starting at the given offset.
         *
         * <p> This method implements the general contract of the corresponding
         * <code>{@link InputStream#read(byte[], int, int) read}</code> method of
         * the <code>{@link InputStream}</code> class.  As an additional
         * convenience, it attempts to read as many bytes as possible by repeatedly
         * invoking the <code>read</code> method of the underlying stream.  This
         * iterated <code>read</code> continues until one of the following
         * conditions becomes true: <ul>
         *
         *   <li> The specified number of bytes have been read,
         *
         *   <li> The <code>read</code> method of the underlying stream returns
         *   <code>-1</code>, indicating end-of-file, or
         *
         *   <li> The <code>available</code> method of the underlying stream
         *   returns zero, indicating that further input requests would block.
         *
         * </ul> If the first <code>read</code> on the underlying stream returns
         * <code>-1</code> to indicate end-of-file then this method returns
         * <code>-1</code>.  Otherwise this method returns the number of bytes
         * actually read.
         *
         * <p> Subclasses of this class are encouraged, but not required, to
         * attempt to read as many bytes as possible in the same fashion.
         *
         * @param      b     destination buffer.
         * @param      off   offset at which to start storing bytes.
         * @param      len   maximum number of bytes to read.
         * @return     the number of bytes read, or <code>-1</code> if the end of
         *             the stream has been reached.
         * @exception  IOException  if this input stream has been closed by
         *                          invoking its {@link #close()} method,
         *                          or an I/O error occurs.
         */
        public synchronized int read(byte b[], int off, int len)
            throws IOException
        {
            getBufIfOpen(); // Check for closed stream
            if ((off | len | (off + len) | (b.length - (off + len))) < 0) {
                throw new IndexOutOfBoundsException();
            } else if (len == 0) {
                return 0;
            }
    
            int n = 0;
            for (;;) {
                int nread = read1(b, off + n, len - n);
                if (nread <= 0)
                    return (n == 0) ? nread : n;
                n += nread;
                if (n >= len)
                    return n;
                // if not closed but no bytes available, return
                InputStream input = in;
                if (input != null && input.available() <= 0)
                    return n;
            }
        }
    
        /**
         * See the general contract of the <code>skip</code>
         * method of <code>InputStream</code>.
         *
         * @exception  IOException  if the stream does not support seek,
         *                          or if this input stream has been closed by
         *                          invoking its {@link #close()} method, or an
         *                          I/O error occurs.
         */
        public synchronized long skip(long n) throws IOException {
            getBufIfOpen(); // Check for closed stream
            if (n <= 0) {
                return 0;
            }
            long avail = count - pos;
    
            if (avail <= 0) {
                // If no mark position set then don't keep in buffer
                if (markpos <0)
                    return getInIfOpen().skip(n);
    
                // Fill in buffer to save bytes for reset
                fill();
                avail = count - pos;
                if (avail <= 0)
                    return 0;
            }
    
            long skipped = (avail < n) ? avail : n;
            pos += skipped;
            return skipped;
        }
    
        /**
         * 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>
         * This method returns the sum of the number of bytes remaining to be read in
         * the buffer (<code>count&nbsp;- pos</code>) and the result of calling the
         * {@link java.io.FilterInputStream#in in}.available().
         *
         * @return     an estimate of the number of bytes that can be read (or skipped
         *             over) from this input stream without blocking.
         * @exception  IOException  if this input stream has been closed by
         *                          invoking its {@link #close()} method,
         *                          or an I/O error occurs.
         */
        public synchronized int available() throws IOException {
            int n = count - pos;
            int avail = getInIfOpen().available();
            return n > (Integer.MAX_VALUE - avail)
                        ? Integer.MAX_VALUE
                        : n + avail;
        }
    
        /**
         * See the general contract of the <code>mark</code>
         * method of <code>InputStream</code>.
         *
         * @param   readlimit   the maximum limit of bytes that can be read before
         *                      the mark position becomes invalid.
         * @see     java.io.BufferedInputStream#reset()
         */
        public synchronized void mark(int readlimit) {
            marklimit = readlimit;
            markpos = pos;
        }
    
        /**
         * See the general contract of the <code>reset</code>
         * method of <code>InputStream</code>.
         * <p>
         * If <code>markpos</code> is <code>-1</code>
         * (no mark has been set or the mark has been
         * invalidated), an <code>IOException</code>
         * is thrown. Otherwise, <code>pos</code> is
         * set equal to <code>markpos</code>.
         *
         * @exception  IOException  if this stream has not been marked or,
         *                  if the mark has been invalidated, or the stream
         *                  has been closed by invoking its {@link #close()}
         *                  method, or an I/O error occurs.
         * @see        java.io.BufferedInputStream#mark(int)
         */
        public synchronized void reset() throws IOException {
            getBufIfOpen(); // Cause exception if closed
            if (markpos < 0)
                throw new IOException("Resetting to invalid mark");
            pos = markpos;
        }
    
        /**
         * Tests if this input stream supports the <code>mark</code>
         * and <code>reset</code> methods. The <code>markSupported</code>
         * method of <code>BufferedInputStream</code> returns
         * <code>true</code>.
         *
         * @return  a <code>boolean</code> indicating if this stream type supports
         *          the <code>mark</code> and <code>reset</code> methods.
         * @see     java.io.InputStream#mark(int)
         * @see     java.io.InputStream#reset()
         */
        public boolean markSupported() {
            return true;
        }
    
        /**
         * Closes this input stream and releases any system resources
         * associated with the stream.
         * Once the stream has been closed, further read(), available(), reset(),
         * or skip() invocations will throw an IOException.
         * Closing a previously closed stream has no effect.
         *
         * @exception  IOException  if an I/O error occurs.
         */
        public void close() throws IOException {
            byte[] buffer;
            while ( (buffer = buf) != null) {
                if (bufUpdater.compareAndSet(this, buffer, null)) {
                    InputStream input = in;
                    in = null;
                    if (input != null)
                        input.close();
                    return;
                }
                // Else retry in case a new buf was CASed in fill()
            }
        }
    }
    View Code

    BufferedInputStream的实现呢是先将流中的一部分数据读取到自己成员变量protected volatile byte buf[];中去,然后再从这个byte数组中去读。而读取到byte数组中的实现就需要依赖传给他的in了,可能是FileInputStream,也可能是ByteArrayInputStream。可以看看fill()方法,就会明白了。

    //这行代码就是利用传进来的流进行读取,读取的byte数组存在buffer中
    int n = getInIfOpen().read(buffer, pos, buffer.length - pos);
    下面是getInIfOpen()方法
    private InputStream getInIfOpen() throws IOException {
            InputStream input = in;
            if (input == null)
                throw new IOException("Stream closed");
            return input;
        }

    BufferedInputStream还实现了一个功能,就是标记和重读。,对了这里需要强调一点,java的原生态io流是不可以回读的,就像个管道一样,我取出了管道前面的水,那么他就不在管道中了。

    具体的用法呢,我还没完全搞明白,先说说我理解明白的部分。。。

    首先我们要关注BufferedInputStream定义的这么几个成员变量

    //从流中读取的总量
    protected int count;
    //当前读取的位置
    protected int pos;
    //标记的位置
    protected int markpos = -1;
    //这个我暂时没想好怎么解释他,不好用官方的解释,和功能不对应
    protected int marklimit;

    以数组{1,2,3,4,5,6}为例

           byte[] b = {1,2,3,4,5,6};
                InputStream out = new BufferedInputStream(new ByteArrayInputStream(b),3);//读取b数组的信息,其中设置BufferedInputStream的缓冲buffer为3
                System.out.println(out.read());//调用read之后pos由0变为1,count由0变为3
                out.mark(1);//此刻marklimit = readlimit;markpos = pos = 1;
                System.out.println(out.read());
                System.out.println(out.read());
                out.reset();//pos = markpos = 1;
                System.out.println(out.read());//所以又从数组1的位置开始读了,
                System.out.println(out.read());
                System.out.println(out.read());
                System.out.println(out.read());
                out.close();

    以上只用了常规的写法,关于marklimit 字段的讨论放到以后去,今天就写到这

  • 相关阅读:
    Linux搭建ElasticSearch环境
    从DDD开始说起
    TFS看板晨会
    TFS看板的迭代规划
    TFS看板规则
    TFS看板的设计
    Api容器在应用架构演化中的用途
    基于Abp的WebApi容器
    线程队列
    动态类型序列化
  • 原文地址:https://www.cnblogs.com/vincentren/p/6523273.html
Copyright © 2011-2022 走看看