• 从构造函数看java.io


    package java.io;

    interface有Closeable、Flushable

    abstract class 有InputStream、OutputStream、Reader、Writer

    class有InputStreamReader、OutputStreamWriter,FileReader、FileWriter

    ----------------------------

    InputStream是所有字节输入流的父类

    package java.io;
    
    /**
     * This abstract class is the superclass of all classes representing
     * an input stream of bytes.
     *
     * <p> Applications that need to define a subclass of <code>InputStream</code>
     * must always provide a method that returns the next byte of input.
     *
     * @author  Arthur van Hoff
     * @see     java.io.BufferedInputStream
     * @see     java.io.ByteArrayInputStream
     * @see     java.io.DataInputStream
     * @see     java.io.FilterInputStream
     * @see     java.io.InputStream#read()
     * @see     java.io.OutputStream
     * @see     java.io.PushbackInputStream
     * @since   JDK1.0
     */
    public abstract class InputStream implements Closeable {

    内部有一个抽象函数。read方法会阻塞,除非:1输入数据可获得,2流读完了,3发生io异常。read的返回值是一个0-255的int,表示一个byte

     /**
         * 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;

    对应的,OutputStream是字节输出流的父类,有一个write抽象函数。参数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;

    FileInputStream直接继承了InputStream,被设计用来读取二进制字节流文件,例如图片。其中read间接调用了本地函数

    /**
     * A <code>FileInputStream</code> obtains input bytes
     * from a file in a file system. What files
     * are  available depends on the host environment.
     *
     * <p><code>FileInputStream</code> is meant for reading streams of raw bytes
     * such as image data. For reading streams of characters, consider using
     * <code>FileReader</code>.
     *
     * @author  Arthur van Hoff
     * @see     java.io.File
     * @see     java.io.FileDescriptor
     * @see     java.io.FileOutputStream
     * @see     java.nio.file.Files#newInputStream
     * @since   JDK1.0
     */
    public
    class FileInputStream extends InputStream
    --------------------------------------
    /**
         * Reads a byte of data from this input stream. This method blocks
         * if no input is yet available.
         *
         * @return     the next byte of data, or <code>-1</code> if the end of the
         *             file is reached.
         * @exception  IOException  if an I/O error occurs.
         */
        public int read() throws IOException {
            return read0();
        }
    
        private native int read0() throws IOException;

    它有三个构造函数public FileInputStream(String)间接调用了public FileInputStream(File)。

     public FileInputStream(String name) throws FileNotFoundException {
            this(name != null ? new File(name) : null);
        }
      public FileInputStream(File file) throws FileNotFoundException {
            String name = (file != null ? file.getPath() : null);
            SecurityManager security = System.getSecurityManager();
            if (security != null) {
                security.checkRead(name);
            }
            if (name == null) {
                throw new NullPointerException();
            }
            if (file.isInvalid()) {
                throw new FileNotFoundException("Invalid file path");
            }
            fd = new FileDescriptor();
            fd.attach(this);
            path = name;
            open(name);
        }
     public FileInputStream(FileDescriptor fdObj) {
            SecurityManager security = System.getSecurityManager();
            if (fdObj == null) {
                throw new NullPointerException();
            }
            if (security != null) {
                security.checkRead(fdObj);
            }
            fd = fdObj;
            path = null;
    
            /*
             * FileDescriptor is being shared by streams.
             * Register this stream with FileDescriptor tracker.
             */
            fd.attach(this);
        }

    看一下java.io.File;

    首先,类注释明确指出了java.io.File是文件和文件夹的抽象表示,不单单是文件哦!

    /**
     * An abstract representation of file and directory pathnames.
     *
    public class File
        implements Serializable, Comparable<File>
    {

    --------------------------

    看字符流吧

    BufferedReader是直接继承自Reader的字符流,并且自带缓冲。缓冲区大小可以指定,不指定采用默认值8192

    /**
     * Reads text from a character-input stream, buffering characters so as to
     * provide for the efficient reading of characters, arrays, and lines.
     *
     * <p> The buffer size may be specified, or the default size may be used.  The
     * default is large enough for most purposes.
     **/
    
    public class BufferedReader extends Reader {

    构造函数有两个,BufferedReader(Reader)调用BufferedReader(Reader,int),其中defaultCharBufferSize=8192;

    需要注意的是,BufferedReader作为一个Reader,本身需要外部的Reader作为参数,我想到了装饰模式。

    BufferedReader是一个Reader但是本身不完整,它本质是对Reader做了装饰。

     /**
         * Creates a buffering character-input stream that uses an input buffer of
         * the specified size.
         *
         * @param  in   A Reader
         * @param  sz   Input-buffer size
         *
         * @exception  IllegalArgumentException  If {@code sz <= 0}
         */
        public BufferedReader(Reader in, int sz) {
            super(in);
            if (sz <= 0)
                throw new IllegalArgumentException("Buffer size <= 0");
            this.in = in;
            cb = new char[sz];
            nextChar = nChars = 0;
        }
    
        /**
         * Creates a buffering character-input stream that uses a default-sized
         * input buffer.
         *
         * @param  in   A Reader
         */
        public BufferedReader(Reader in) {
            this(in, defaultCharBufferSize);
        }

    BufferedInputStream也是一样,不同的是BufferedInputStream继承InputStream,是对字节流的装饰。并且BufferedInputStream提供了对mark和reset的支持。

    /**
     * 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 {

    构造函数如下

    /**
         * 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, DEFAULT_BUFFER_SIZE);
        }
    
        /**
         * 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 {@code size <= 0}.
         */
        public BufferedInputStream(InputStream in, int size) {
            super(in);
            if (size <= 0) {
                throw new IllegalArgumentException("Buffer size <= 0");
            }
            buf = new byte[size];
        }

    -----------------------

    从字节流到字符流的桥梁

    InputStreamReader继承自Reader,它的主要工作是将字节流解码成字符流。

    InputStreamReader里面有一个变量StreamDecoder sd,实际工作其实都是有这个sd来做的。说不出来这是什么模式,但不是代理模式。sun.nio.cs.StreamDecoder的源码没有找到。

    /**
     * An InputStreamReader is a bridge from byte streams to character streams: It
     * reads bytes and decodes them into characters using a specified {@link
     * java.nio.charset.Charset charset}.  The charset that it uses
     * may be specified by name or may be given explicitly, or the platform's
     * default charset may be accepted.
     *
     * <p> Each invocation of one of an InputStreamReader's read() methods may
     * cause one or more bytes to be read from the underlying byte-input stream.
     * To enable the efficient conversion of bytes to characters, more bytes may
     * be read ahead from the underlying stream than are necessary to satisfy the
     * current read operation.
     *
     * <p> For top efficiency, consider wrapping an InputStreamReader within a
     * BufferedReader.  For example:
     *
     * <pre>
     * BufferedReader in
     *   = new BufferedReader(new InputStreamReader(System.in));
     * </pre>
     *
     * @see BufferedReader
     * @see InputStream
     * @see java.nio.charset.Charset
     *
     * @author      Mark Reinhold
     * @since       JDK1.1
     */
    
    public class InputStreamReader extends Reader {
    private final StreamDecoder sd;

    其构造函数如下

     /**
         * Creates an InputStreamReader that uses the default charset.
         *
         * @param  in   An InputStream
         */
        public InputStreamReader(InputStream in) {
            super(in);
            try {
                sd = StreamDecoder.forInputStreamReader(in, this, (String)null); // ## check lock object
            } catch (UnsupportedEncodingException e) {
                // The default encoding should always be available
                throw new Error(e);
            }
        }
    
        /**
         * Creates an InputStreamReader that uses the named charset.
         *
         * @param  in
         *         An InputStream
         *
         * @param  charsetName
         *         The name of a supported
         *         {@link java.nio.charset.Charset charset}
         *
         * @exception  UnsupportedEncodingException
         *             If the named charset is not supported
         */
        public InputStreamReader(InputStream in, String charsetName)
            throws UnsupportedEncodingException
        {
            super(in);
            if (charsetName == null)
                throw new NullPointerException("charsetName");
            sd = StreamDecoder.forInputStreamReader(in, this, charsetName);
        }
    
        /**
         * Creates an InputStreamReader that uses the given charset.
         *
         * @param  in       An InputStream
         * @param  cs       A charset
         *
         * @since 1.4
         * @spec JSR-51
         */
        public InputStreamReader(InputStream in, Charset cs) {
            super(in);
            if (cs == null)
                throw new NullPointerException("charset");
            sd = StreamDecoder.forInputStreamReader(in, this, cs);
        }
    
        /**
         * Creates an InputStreamReader that uses the given charset decoder.
         *
         * @param  in       An InputStream
         * @param  dec      A charset decoder
         *
         * @since 1.4
         * @spec JSR-51
         */
        public InputStreamReader(InputStream in, CharsetDecoder dec) {
            super(in);
            if (dec == null)
                throw new NullPointerException("charset decoder");
            sd = StreamDecoder.forInputStreamReader(in, this, dec);
        }

    这四个构造函数都是调用了StreamDecoder.forInputStreamReader函数

    ----------------------------

    总结一下,在这几个常用的io流中,本质上说程序员只能从文件构造流,或者使用外部提供的流,例如System.in,socket.getInputStream;

    其他的类都是对流的装饰。

  • 相关阅读:
    数据访问(从数据库中访问数据)
    加载类、设计模式(单例模式和工厂模式)
    面向对象之静态
    面向对象三大特性之继承和多态
    面向对象三大特性之封装
    面向对象基础知识
    mysql下载与安装过程
    Idea添加依赖的步骤:
    Java JDBC 在IDEA环境下连接MySQL
    JAVA中集合HashMap嵌套联系
  • 原文地址:https://www.cnblogs.com/afraidToForget/p/6623503.html
Copyright © 2020-2023  润新知