zoukankan      html  css  js  c++  java
  • 重新认识Java流这种数据结构

    一、背景

    基于之前文章中的疑问,重新学习了一下《Java编程思想》关于Java I/O系统章节中的流的相关部分。因此,这篇文章就是记录下结合对Servlet流,重新学习IO的感受。

    1. 为什么会有流这种数据结构?
      答:一个系统一般都会存在很多的系统输入与输出。数据格式也各不相同,例如二进制、字节、字符等。而且数据源也是各种各样,例如:字节数组、String对象、文件、管道、其他流、网络I/O等。所以流就是用来屏蔽这些底层细节的,让你不用去关注每个输入或输出对数据的具体处理细节。

    二、Java流

    流这种数据结构,基本上都是伴随着I/O出现。这里有一个我之前对I/O的一个很刻板的印象就是:I/O就是指的读写网络数据、读写磁盘。但是实际上I/O并不止于此。

    Input输入:
    指的是可以从数据源,读取数据到程序中。那数据源就不仅仅是网络、磁盘,也可以是一个字节数组、String对象、管道等
    Output输出:
    是可以将程序中的数据,写到目的地。同样,目的地也可以是String对象、磁盘、字节数组、网络等等。

    总结来说就类似下图:

    目前Java中最基本的输入流是InputStreamReader. 它们都是抽象类,其中的抽象方法就是read(). 但是InputStream是用来读取字节的,Reader是用来读取字符的。
    下面是InputStream中的抽象方法read()

     /**
         * 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是读取流中的下一个字节,并将该字节转化为int返回。而Reader中的抽象方法为:

    /**
         * Reads characters into a portion of an array.  This method will block
         * until some input is available, an I/O error occurs, or the end of the
         * stream is reached.
         *
         * @param      cbuf  Destination buffer
         * @param      off   Offset at which to start storing characters
         * @param      len   Maximum number of characters to read
         *
         * @return     The number of characters read, or -1 if the end of the
         *             stream has been reached
         *
         * @exception  IOException  If an I/O error occurs
         */
        abstract public int read(char cbuf[], int off, int len) throws IOException;
    

    可以看到读取字符流,需要传入一个char数组最为读取容器,一个偏移量和指定读取的长度。而且返回值也是int,但是这个返回值表达的却是读取了多少个字符。
    在这两个read方法中,都一点说明就是,除非发生IO异常或者流读完了,否则会一直阻塞。

    三、关于流的重复读

    首先流只能读一次这个说法肯定是错误的,具体要看流的实现类。
    在两种基础的流对象中,都有mark()、reset()以及markSupported()方法,在不同的子类中可以覆写,默认是不支持mart和reset的。
    例如:ServletInputStream就是直接继承InputStream,因此HttpServletRequest获取到的输入流中,确实不支持重复读。但是像ByteArrayInputStream就是支持重复读的。

    四、ByteBuffer

    ByteBuffer是NIO中我们用来与Channel打交道的对象,无论读还是写都是通过这个对象,并且这个对象是支持重复读的。
    而ServletInputStream的实现类CoyoteInputStream中使用的InputBuffer里层就是用的ByteBuffer和CharBuffer,所以为什么实际中ServletInputStream不设计为可重复读,现在也不能理解。

  • 相关阅读:
    WebStorm使用Vue
    hive的简单操作
    hbase的简单操作
    CentOS 7 配置hadoop(五) 配置sqoop(伪分布)
    CentOS7配置hadoop集群
    CentOS 7 配置hadoop(四) 配置hive(伪分布)
    CentOS 7 配置hadoop(三) 配置hbase(伪分布)
    五种变量创建的方法
    GO练习题
    第一次作业总结
  • 原文地址:https://www.cnblogs.com/bencakes/p/14519254.html
Copyright © 2011-2022 走看看