您的位置:首页 > 编程语言 > Java开发

JAVA基础1-JAVA IO学习笔记

2019-06-29 17:25 357 查看

JAVA IO学习笔记

  • OutputStream
  • Reader
  • Writer
  • 高级篇
  • IO的同步异步和阻塞非阻塞
  • 初级篇

    InputStream

    结构图

    具体类

    InputStream抽象类,定义了read、mark、reset、close方法。并未真正实现内容。其中的mark(标记mark值)和reset(将当前pos设置为mark)方法只有子类ByteArrayInputStream、BufferedInputStream和PushbackInputStream实现具体方法。

    FileInputStream继承InputStream抽象类,具体实现read、close方法(具体调用的是native的方法)。

    ObjectInputStream继承InputStream抽象类并实现ObjectInput接口,对对象的读操作,而对象必须实现Serializable接口。除了实现read、close方法外,还实现readLong、readShort、readFloat、readChar等java继承类型的方法,另外readObject则是调用对象的toString方法。。其内部实现实际是采用DataInputStream的方法。

    ByteArrayInputStream继承InputStream抽象类,对一个数据的byte进行读操作。除了实现read、close方法外,还实现mark、rest方法。入参是一个数据的byte。

    PipedInputStream继承InputStream抽象类,对一个数据的byte进行操作,默认大小是1024。此类用于线程之间信息发送,一般与PipedOutStream配对使用。有2个重要方法。第一个connect方法,设置输入的PipedOutStream;第二个receive方法,用于接收PipedOutStream的输入,即PipedOutStream的write最后是调用PipedInputStream的receive。

    FilterInputStream继承抽象类,使用装饰者模式的设计一些特殊功能的InputStream。

    DataInputStream继承FilterInputStream类,是InputStream的修饰者,主要增加java基础类型的读操作。如:readLong、readShort、readFloat、readChar等。

    BufferedInputStream继承FilterInputStream类,是InputStream的修饰者,入参为InputStream,主要增加缓存功能。

    PushbackInputStream继承FilterInputStream类,是InputStream的修饰者,主要增加unread方法,实现回写效果。

    SequenceInputStream继承InputStream抽象类,实现多个InputStream的操作,可以同时初始化多个InputStream,然后依次读取。

    StringBufferInputStream继承InputStream抽象类,入参为String。此类已经作废。

    OutputStream

    结构图

    具体类

    OutputStream抽象类,定义了write、flush、close方法。并未真正实现内容。

    FileOutputStream继承OutputStream抽象类,构造函数的入参可以说File或者文件名,具体实现write、close方法(具体调用的是native的方法)。

    ObjectOutputStream继承OutputStream抽象类并实现ObjectOutput接口,对对象的写操作,而对象必须实现Serializable接口。除了实现write、flush、close方法外,还实现readLong、writeShort、writeFloat、writeChar等java继承类型的方法,另外writeObject则是调用对象的toString方法。。其实现通过采用内部类BlockataOutputStream的方法,内部类实际采用DataOutputStream的操作。

    ByteArrayOutputStream继承OutputStream抽象类,对一个数据的byte进行写操作。除了实现write、close方法外,还实现mark、rest方法。入参是一个数据的byte。

    PipedOutputStream继承OutputStream抽象类,对一个数据的byte进行操作,默认大小是1024。此类用于线程之间信息发送,一般与PipedInputStream配对使用。增加一个connect方法,设置输入的PipedInputStream。

    FilterOutputStream继承抽象类,使用装饰者模式的设计一些特殊功能的OutputStream。

    DataOutputStream继承FilterOutputStream类,是OutputStream的修饰者,主要增加java基础类型的读操作。如:writeLong、writeShort、writeFloat、writeChar等。

    BufferedOutputStream继承FilterOutputStream类,是OutputStream的修饰者,主要增加缓存功能。

    PrintStream继承FilterOutputStream类,是OutputStream的修饰者,主要增加unwrite方法,实现写到控制台功能。主要通过BufferedWriter来实现功能。增加print等一些功能。

    Reader

    结构图

    具体类

    Reader抽象类,定义read、mark、reset、close方法,并未实现具体方法。其中mark、reset方法只有子类StringReader、BufferReader、CharArrayReader和PushbackReader实现。

    InputStreamReader继承Reader抽象类,使用InputStream和编码作为入参,通过StreamDecoder进行编码转换(字节转字符)实现read、mark、close方法。增加getEncoding返回获取编码。

    FileReader继承InputStreamReader抽象类,使用File作为入参,实际创建FileInputStream并将其传入StreamDecoder。

    StringReader继承Reader抽象类,使用String作为入参,主要对入参的String进行操作。同时实现mark和reset方法。

    PipedReader继承Reader抽象类,对一个数组的char进行操作,默认大小是1024。此类用于线程之间信息发送,一般与PipedWriter配对使用。增加一个connect方法,设置输入的PipedWriter。

    BufferReader继承Reader抽象类,入参是Reader。实现缓存效果。增加一个重要的方法readLine,一行数据写入。

    CharArrayReader继承Reader抽象类,对一数组的char进行操作,入参为数组的char。同时实现mark和reset方法。

    FilterReader继承抽象类,使用装饰者模式的设计一些特殊功能的Reader。

    PushbackReader继承FilterReader类,是Reader的修饰者,主要增加unread方法,实现回写效果。

    Writer

    结构图

    具体类

    Writer抽象类,定义write、flush、close方法,并未实现具体方法。

    InputStreamWriter继承Writer抽象类,使用OutputStream和编码作为入参,通过StreamEncoder进行编码转换(字节转字符)实现write、flush、close方法。增加flushBuffer刷新缓存。

    FileWriter继承OutputStreamWriter抽象类,使用File作为入参,实际创建FileOutputStream并将其传入StreamEncoder。

    StringWriter继承Writer抽象类,主要对StringBuffer进行操作。

    PipedWriter继承Writer抽象类,对一个数组的char进行操作,默认大小是1024。此类用于线程之间信息发送,一般与PipedWriter配对使用。增加一个connect方法,设置输入的PipedWriter。

    BufferedWriter继承Writer抽象类,入参是Writer。实现缓存效果。增加一个重要的方法newLine,换行功能。

    CharArrayWriter继承Writer抽象类,对一数组的char进行操作,入参为数组的char。同时实现mark和reset方法。

    PrintWriter继承Writer抽象类,主要通过PrintStream进行对控制台输出。

    FilterWriter继承抽象类,使用装饰者模式的设计一些特殊功能的Writer。目前暂未有装饰者。

    高级篇

    Java.nio与java.io的区别。

    1. 提高的读写速度,原先的io是阻塞型的,nio是将I/O交个操作系统,这样更适合与并发操作。
    2. 数据的打包和传输方式,原先io是采用流方式,而nio是采用缓冲区方式。
    3. selector的作用,运行一个线程使用多个通道。

    具体类

    RandomAccessFile

    实现DataOutput, DataInput接口。实际上与inputstream和outputstream无关系。作为一个可以同时实现读写文件的操作。主要实现seek、skipBytes方法用于操作文件位置,同时实现length( )、getFilePointer( )获取一些文件属性。此接口将逐渐被NIO取代。

    Channel

    通道类似流,但又有些不同:

    1. 既可以从通道中读取数据,又可以写数据到通道。但流的读写通常是单向的。
    2. 通道可以异步地读写。
    3. 通道中的数据总是要先读到一个Buffer,或者总是要从一个Buffer中写入。
      这些是Java NIO中最重要的通道的实现:
    4. FileChannel 从文件中读写数据。
    5. DatagramChannel 能通过UDP读写网络中的数据。
    6. SocketChannel 能通过TCP读写网络中的数据。
    7. ServerSocketChannel可以监听新进来的TCP连接,像Web服务器那样。对每一个新进来的连接都会创建一个SocketChannel。

    Buffer

    Java NIO中的Buffer用于和NIO通道进行交互。数据是从通道读入缓冲区,从缓冲区写入到通道中的。

    使用Buffer读写数据一般遵循以下四个步骤:

    1. 写入数据到Buffer
    2. 调用flip()方法
    3. 从Buffer中读取数据
    4. 调用clear()方法或者compact()方法

    Buffer的capacity,position和limit

    1. capacity
      作为一个内存块,Buffer有一个固定的大小值,也叫“capacity”.你只能往里写capacity个byte、long,char等类型。一旦Buffer满了,需要将其清空(通过读数据或者清除数据)才能继续写数据往里写数据。
    2. position
      当你写数据到Buffer中时,position表示当前的位置。初始的position值为0.当一个byte、long等数据写到Buffer后, position会向前移动到下一个可插入数据的Buffer单元。position最大可为capacity – 1.
      当读取数据时,也是从某个特定位置读。当将Buffer从写模式切换到读模式,position会被重置为0. 当从Buffer的position处读取数据时,position向前移动到下一个可读的位置。
    3. limit
      在写模式下,Buffer的limit表示你最多能往Buffer里写多少数据。 写模式下,limit等于Buffer的capacity。
      当切换Buffer到读模式时, limit表示你最多能读到多少数据。因此,当切换Buffer到读模式时,limit会被设置成写模式下的position值。换句话说,你能读到之前写入的所有数据(limit被设置成已写数据的数量,这个值在写模式下就是position)

    Java NIO 有以下Buffer类型

    1. ByteBuffer
    2. MappedByteBuffer
    3. CharBuffer
    4. DoubleBuffer
    5. FloatBuffer
    6. IntBuffer
    7. LongBuffer
    8. ShortBuffer

    Scatter/Gather

    分散(scatter)从Channel中读取是指在读操作时将读取的数据写入多个buffer中。因此,Channel将从Channel中读取的数据“分散(scatter)”到多个Buffer中。
    聚集(gather)写入Channel是指在写操作时将多个buffer的数据写入同一个Channel,因此,Channel 将多个Buffer中的数据“聚集(gather)”后发送到Channel。
    FileChannel
    实现ByteChanel的抽象类。Java NIO中的FileChannel是一个连接到文件的通道。可以通过文件通道读写文件。FileChannel无法设置为非阻塞模式,它总是运行在阻塞模式下。增加一些特殊方法,比如:size、truncat、force等方法。

    SocketChannel

    实现ByteChanel的抽象类。Java NIO中的SocketChannel是一个连接到TCP网络套接字的通道。可以通过以下2种方式创建SocketChannel:第一种是打开一个SocketChannel并连接到互联网上的某台服务器;第二种是一个新连接到达ServerSocketChannel时,会创建一个SocketChannel。增加一些特殊方法,比如:connect、bind、socket等方法。

    ServerSocketChannel

    实现ByteChanel的抽象类。Java NIO中的 ServerSocketChannel 是一个可以监听新进来的TCP连接的通道, 就像标准IO中的ServerSocket一样。ServerSocketChannel类在 java.nio.channels包中。增加一些特殊方法,比如:connect、bind、accept、socket等方法。

    DatagramChannel

    实现ByteChanel的抽象类。Java NIO中的DatagramChannel是一个能收发UDP包的通道。因为UDP是无连接的网络协议,所以不能像其它通道那样读取和写入。它发送和接收的是数据包。

    Pipe

    Java NIO 管道是2个线程之间的单向数据连接。Pipe有一个source通道和一个sink通道。数据会被写到sink通道,从source通道读取。主要用于线程间的操作。

    IO的同步异步和阻塞非阻塞

    流程


    流程描述:应用进程在调用IO(无论是磁盘还是网络IO),会线程从用户状态切换成内核状态。调用recv确认数据是否准备完成,如果未准备好,则一直等到。当数据准备好,就复制数据到用户空间,返回成功,并切换回用户状态。
    等待数据时间:当内核没有准备好数据,线程等待数据准备完成的时间。(阻塞/非阻塞)
    复制数据到用户空间的时间:内核缓存的数据复制到用户空间。(同步/异步)

    阻塞


    当应用进程调用recv时,发现没有数据时,一直等待,则是阻塞IO。

    非阻塞


    当系统调用recv时,发现没有数据就返回,过一段时间继续调用recv确认,这样就在等待数据时,用户进程可以做其它事情。这种模式称为非阻塞IO。

    IO复用模型


    应用进程先调用select、poll或者epoll,确认是否数据已完成,但是这个过程是阻塞的,只是没有阻塞recv。从这个角度,这样就在等待数据时,用户进程可以做其它事情,可以称为非阻塞IO。

    信号驱动模型


    应用进程先调用sigaction注册信号函数,注册到内核。当数据准备好时,内核会执行信号函数(里面包含recv)。这样就在等待数据时,用户进程可以做其它事情。所以这种模式也称为非阻塞IO。

    异步IO模型


    应用进程调用aio_read就即可返回,让内核自己等待数据完成,当完成时,内核还负责复制数据到用户空间,再通知应用进程。这个过程,复制数据的过程应用进程都不需要等待的,我们称为异步IO。当然,这个也是非阻塞。

    内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
    标签: