JAVA基础1-JAVA IO学习笔记
JAVA 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的区别。
- 提高的读写速度,原先的io是阻塞型的,nio是将I/O交个操作系统,这样更适合与并发操作。
- 数据的打包和传输方式,原先io是采用流方式,而nio是采用缓冲区方式。
- selector的作用,运行一个线程使用多个通道。
具体类
RandomAccessFile
实现DataOutput, DataInput接口。实际上与inputstream和outputstream无关系。作为一个可以同时实现读写文件的操作。主要实现seek、skipBytes方法用于操作文件位置,同时实现length( )、getFilePointer( )获取一些文件属性。此接口将逐渐被NIO取代。
Channel
通道类似流,但又有些不同:
- 既可以从通道中读取数据,又可以写数据到通道。但流的读写通常是单向的。
- 通道可以异步地读写。
- 通道中的数据总是要先读到一个Buffer,或者总是要从一个Buffer中写入。
这些是Java NIO中最重要的通道的实现: - FileChannel 从文件中读写数据。
- DatagramChannel 能通过UDP读写网络中的数据。
- SocketChannel 能通过TCP读写网络中的数据。
- ServerSocketChannel可以监听新进来的TCP连接,像Web服务器那样。对每一个新进来的连接都会创建一个SocketChannel。
Buffer
Java NIO中的Buffer用于和NIO通道进行交互。数据是从通道读入缓冲区,从缓冲区写入到通道中的。
使用Buffer读写数据一般遵循以下四个步骤:
- 写入数据到Buffer
- 调用flip()方法
- 从Buffer中读取数据
- 调用clear()方法或者compact()方法
Buffer的capacity,position和limit
- capacity
作为一个内存块,Buffer有一个固定的大小值,也叫“capacity”.你只能往里写capacity个byte、long,char等类型。一旦Buffer满了,需要将其清空(通过读数据或者清除数据)才能继续写数据往里写数据。 - position
当你写数据到Buffer中时,position表示当前的位置。初始的position值为0.当一个byte、long等数据写到Buffer后, position会向前移动到下一个可插入数据的Buffer单元。position最大可为capacity – 1.
当读取数据时,也是从某个特定位置读。当将Buffer从写模式切换到读模式,position会被重置为0. 当从Buffer的position处读取数据时,position向前移动到下一个可读的位置。 - limit
在写模式下,Buffer的limit表示你最多能往Buffer里写多少数据。 写模式下,limit等于Buffer的capacity。
当切换Buffer到读模式时, limit表示你最多能读到多少数据。因此,当切换Buffer到读模式时,limit会被设置成写模式下的position值。换句话说,你能读到之前写入的所有数据(limit被设置成已写数据的数量,这个值在写模式下就是position)
Java NIO 有以下Buffer类型
- ByteBuffer
- MappedByteBuffer
- CharBuffer
- DoubleBuffer
- FloatBuffer
- IntBuffer
- LongBuffer
- 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。当然,这个也是非阻塞。
- Java基础学习笔记十九 IO
- Java IO学习笔记(一):BIO,NIO,AIO基础概念
- 黑马程序员---Java基础学习笔记(IO-前篇)
- java基础-用IO演示文件的复制过程(学习笔记)
- 黑马程序员---Java基础学习笔记IO-1
- IO流02--毕向东JAVA基础教程视频学习笔记
- 黑马程序员---Java基础学习笔记IO
- Java IO编程 学习笔记 (其一:基础部分)
- java基础学习笔记(四)JAVA IO
- 黑马程序员---Java基础学习笔记IO-2
- Java基础学习笔记24(IO)
- 黑马程序员---Java基础学习笔记(IO-后篇)
- [学习笔记]Java基础_IO(包含对象流序列化使用和RandomAccessFile 类的使用)
- Java基础学习笔记25(IO)
- Java学习笔记之语言基础―― Java中浮点数除0问题
- Java IO学习基础之读写文本文件
- 【JAVA学习笔记】面向对象基础
- Java基础学习笔记(九)Comparable接口、Map接口、泛型
- Java IO学习笔记+代码(3)
- Java IO学习笔记:字符流